[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/plotdevice/plotdevice/main/plotdevice/gui/widgets.py [Back]  [Original]

# encoding: utf-8
import os, re
from collections import OrderedDict
from ..lib.cocoa import *
from math import floor, ceil
import objc

## classes instantiated by PlotDeviceDocument.xib & PlotDeviceScript.xib

class StatusView(NSView):
    spinner = IBOutlet()
    counter = IBOutlet()
    cancel = IBOutlet()

    def awakeFromNib(self):
        self.cancel.setHidden_(True)
        self._state = 'idle'
        self._finishing = False

        opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp);
        trackingArea = NSTrackingArea.alloc().initWithRect_options_owner_userInfo_(self.bounds(), opts, self, None)
        self.addTrackingArea_(trackingArea)

        self.cancel.cell().setHighlightsBy_(NSContentsCellMask)
        self.cancel.cell().setShowsStateBy_(NSContentsCellMask)
        self.counter.setHidden_(True)

    def beginExport(self):
        self._state = 'run'

        self.spinner.stopAnimation_(None)
        self.cancel.setHidden_(True)
        self.spinner.setIndeterminate_(False)
        self.spinner.setDoubleValue_(0)
        self.spinner.startAnimation_(None)

        self.counter.setHidden_(False)
        self.counter.setStringValue_("")

    def updateExport_total_(self, written, total):
        self.spinner.setMaxValue_(total)
        self.spinner.setDoubleValue_(written)
        msg = "Frame {:,}/{:,}".format(written, total) if written 0:
                    pOrigin = (win.origin.x - pw, win.origin.y + win.size.height - ph - 38)
                else:
                    pOrigin = (win.origin.x + win.size.width - pw - 15, win.origin.y + 15)
                self.panel.setFrame_display_animate_( (pOrigin, (pw,ph)), True, True )
                self.positioned = True

            elif needs_resize:
                pOrigin.y -= ph-pSize.height
                self.panel.setFrame_display_animate_( (pOrigin, (pw,ph)), True, True )

            # reposition the elements of each row to fit the new panel size and row contents
            for idx, v in enumerate(self.rows.values()):
                v.updateLayout(col, pw - 10 - num_w, pw, idx*30)

            self.panel.orderFront_(None)


from ..context import RGB, CMYK
class ExportSheet(NSObject):
    # the script whose doExportAsImage and doExportAsMovie methods will be called
    script = IBOutlet()

    # Image export settings
    imageAccessory = IBOutlet()
    imageFormat = IBOutlet()
    imageZoom = IBOutlet()
    imagePageCount = IBOutlet()
    imagePagination = IBOutlet()
    imageCMYK = IBOutlet()

    # Movie export settings
    movieAccessory = IBOutlet()
    movieFormat = IBOutlet()
    movieFrames = IBOutlet()
    movieFps = IBOutlet()
    movieLoop = IBOutlet()
    movieBitrate = IBOutlet()

    def awakeFromNib(self):
        self.formats = dict(image=(0, 'pdf', 0,0, 'png', 'jpg', 'heic', 'tiff', 'gif', 0,0, 'pdf', 'eps'), movie=('mov', 'mov', 'gif'))
        self.movie = dict(format='mov', first=1, last=150, fps=30, bitrate=1, loop=0, codec=0)
        self.image = dict(format='pdf', zoom=1.0, first=1, last=1, cmyk=False, single=True)
        self.last = None

    @objc.python_method
    def beginExport(self, kind):
        # configure the accessory controls
        if kind=='image':
            format = self.image['format']
            accessory = self.imageAccessory

            if self.image['single']:
                self.imageFormat.selectItemAtIndex_(1)
            else:
                format_idx = 2 + self.formats['image'][2:].index(self.image['format'])
                self.imageFormat.selectItemAtIndex_(format_idx)
            self.imagePageCount.setIntValue_(self.image['last'])

            self.updatePagination()
            self.updateColorMode()

        elif kind=='movie':
            format = self.movie['format']
            accessory = self.movieAccessory
            format_idx = self.formats['movie'].index(self.movie['format'])
            should_loop = self.movie['format']=='gif' and self.movie['loop']==-1
            self.movieFrames.setIntValue_(self.movie['last'])
            self.movieFps.setIntValue_(self.movie['fps'])
            self.movieFormat.selectItemAtIndex_(format_idx)
            self.movieLoop.setState_(NSOnState if should_loop else NSOffState)
            self.movieLoop.setEnabled_(format=='gif')
            self.movieBitrate.setEnabled_(format!='gif')
            self.movieBitrate.selectItemWithTag_(self.movie['bitrate'])

        # set the default filename and save dir
        # path = self.script.fileName()
        path = self.script.path
        if path:
            dirName, fileName = os.path.split(path)
            fileName, ext = os.path.splitext(fileName)
            fileName += "." + format
        else:
            dirName, fileName = None, "Untitled.%s"%format

        # If a file was already exported, use that folder/filename as the default.
        if self.last is not None:
            dirName, fileName = self.last
            fileName, ext = os.path.splitext(fileName)

        # create the sheet
        exportPanel = NSSavePanel.savePanel()
        exportPanel.setNameFieldLabel_("Export To:")
        exportPanel.setPrompt_("Export")
        exportPanel.setCanSelectHiddenExtension_(True)
        exportPanel.setShowsTagField_(False)
        exportPanel.setAllowedFileTypes_([format])
        exportPanel.setAccessoryView_(accessory)
        self.exportPanel = exportPanel

        # present the dialog
        callback = "exportPanelDidEnd:returnCode:contextInfo:"
        context = 0 if kind=='image' else 1
        exportPanel.beginSheetForDirectory_file_modalForWindow_modalDelegate_didEndSelector_contextInfo_(
            dirName, fileName, NSApp().mainWindow(), self, callback, context
        )

    def exportPanelDidEnd_returnCode_contextInfo_(self, panel, returnCode, context):
        fname = panel.filename()
        panel.close()
        panel.setAccessoryView_(None)

        # if the user clicked Save:
        if returnCode:
            if context:
                kind, opts = 'movie', self.movieState()
            else:
                kind, opts = 'image', self.imageState()
            setattr(self, kind, dict(opts))  # save the options for next time
            self.last = os.path.split(fname) # save the path we exported to
            self.script.exportInit(kind, fname, opts)

    def movieState(self, key=None):
        fmts = self.formats['movie']
        fmt_idx = self.movieFormat.indexOfSelectedItem()
        state = dict(format = fmts[fmt_idx],
                     first=1,
                     last=self.movieFrames.intValue(),
                     fps=self.movieFps.floatValue(),
                     loop=-1 if self.movieLoop.state()==NSOnState else 0,
                     bitrate=self.movieBitrate.selectedItem().tag(),
                     codec=fmt_idx ) # 0=h265 1=h264
        if key:
            return state[key]
        return state

    def imageState(self, key=None):
        fmts = self.formats['image']
        fmt_idx = self.imageFormat.indexOfSelectedItem()
        state = dict(format=fmts[fmt_idx],
                     zoom=self.image['zoom'],
                     first=1,
                     cmyk=self.imageCMYK.state()==NSOnState,
                     single=fmt_idx==1,
                     last=self.imagePageCount.intValue())
        if key:
            return state[key]
        return state

    def updatePagination(self):
        label = 'Pages:' if self.imageState('single') else 'Files:'
        self.imagePagination.setStringValue_(label)

    def updateColorMode(self):
        format = self.imageState('format')
        can_cmyk = format in ('pdf','eps','tiff','jpg')
        self.imageCMYK.setEnabled_(can_cmyk)
        if not can_cmyk:
            self.imageCMYK.setState_(NSOffState)

    @IBAction
    def imageFormatChanged_(self, sender):
        format = self.formats['image'][sender.indexOfSelectedItem()]
        self.exportPanel.setAllowedFileTypes_([format])
        self.updateColorMode()
        self.updatePagination()

    @IBAction
    def imageZoomStepped_(self, sender):
        step = sender.intValue()
        sender.setIntValue_(0)

        self.imageZoomChanged_(None) # reflect any editing in text field
        pct = self.image['zoom'] * 100

        if step > 0:
            pct = 100 * ceil((pct + 1) / 100)
        elif step < 0:
            pct = 100 * floor((pct - 1) / 100)

        if 0 < pct < 10000:
            self.image['zoom'] = pct / 100
            self.imageZoom.setStringValue_("%i%%" % pct)

    @IBAction
    def imageZoomChanged_(self, sender):
        pct = self.imageZoom.intValue()
        if pct > 0:
            self.image['zoom'] = pct / 100
        else:
            pct = self.image['zoom'] * 100
        self.imageZoom.setStringValue_("%i%%" % pct)

    @IBAction
    def movieFormatChanged_(self, sender):
        format = self.formats['movie'][sender.indexOfSelectedItem()]
        self.exportPanel.setAllowedFileTypes_([format])
        is_gif = format=='gif'
        self.movieLoop.setState_(NSOnState if is_gif else NSOffState)
        self.movieLoop.setEnabled_(is_gif)
        self.movieBitrate.setEnabled_(not is_gif)


Web Proxy Viewer  |  New URL  |  Original Page