def Variable(self, variables, workSpace):
        """
        Build small UI for variables in a script.

        The `workSpace` is usually `globals()`
        as you want to insert the variable in the current workspace.
        It is required that `workSpace` is a `dict` object.

        .. image:: assets/variables.png

        .. showcode:: /../examples/variables.py
        """

        document = AppKit.NSDocumentController.sharedDocumentController(
        ).currentDocument()
        if not document:
            raise DrawBotError("There is no document open")
        controller = document.vanillaWindowController
        try:
            controller._variableController.buildUI(variables)
            controller._variableController.show()
        except:
            controller._variableController = VariableController(
                variables, controller.runCode, document)

        data = controller._variableController.get()
        for v, value in data.items():
            workSpace[v] = value
    def size(self, width, height=None):
        """
        Set the width and height of the canvas.
        Without calling `size()` the default drawing board is 1000 by 1000 points.

        Alternatively `size('A4')` with a supported papersizes or `size('screen')` setting the current screen size as size, can be used.

        Afterwards the functions `width()` and `height()` can be used for calculations.

        It is advised to use `size()` always at the top of the script and not use `size()`
        in a multiple page document use `newPage(w, h)` to set the correct dimentions directly.

        .. showcode:: /../examples/size.py

        All supported papersizes: 10x14, 10x14Landscape, A0, A0Landscape, A1, A1Landscape, A2, A2Landscape, A3, A3Landscape, A4, A4Landscape, A4Small, A4SmallLandscape, A5, A5Landscape, B4, B4Landscape, B5, B5Landscape, Executive, ExecutiveLandscape, Folio, FolioLandscape, Ledger, LedgerLandscape, Legal, LegalLandscape, Letter, LetterLandscape, LetterSmall, LetterSmallLandscape, Quarto, QuartoLandscape, Statement, StatementLandscape, Tabloid, TabloidLandscape.
        """
        if width in _paperSizes:
            width, height = _paperSizes[width]
        if width == "screen":
            width, height = AppKit.NSScreen.mainScreen().frame().size
        if height is None:
            width, height = width
        self._width = width
        self._height = height
        if not self._instructionsStack:
            self.newPage(width, height)
        else:
            raise DrawBotError(
                "It is advised to use 'size()' at the top of a script.")
    def saveImage(self, paths, multipage=None):
        """
        Save or export the canvas to a specified format.
        The argument `paths` can either be a single path or a list of paths.

        The file extension is important because it will determine the format in which the image will be exported.

        All supported file extensions: `pdf`, `svg`, `png`, `jpg`, `jpeg`, `tiff`, `tif`, `gif`, `bmp` and `mov`.

        * A `pdf` can be multipage. If `multipage` is `False` only the current page is saved.
        * A `mov` will use each page as a frame.
        * A `gif` can be animated when there are multiple pages and it will use each page as a frame.
        * All images and `svg` formats will only save the current page. If `multipage` is `True` all pages are saved to disk (a page index will be added to the file name).

        .. showcode:: /../examples/saveImage.py
        """
        if isinstance(paths, (str, unicode)):
            paths = [paths]
        for path in paths:
            path = optimizePath(path)
            dirName = os.path.dirname(path)
            if not os.path.exists(dirName):
                raise DrawBotError("Folder '%s' doesn't exists" % dirName)
            base, ext = os.path.splitext(path)
            ext = ext.lower()[1:]
            context = getContextForFileExt(ext)
            self._drawInContext(context)
            context.saveImage(path, multipage)
 def _tryInstallFontFromFontName(self, fontName):
     # check if the fontName is actually a path
     if os.path.exists(fontName):
         fontPath = os.path.abspath(fontName)
         ext = os.path.splitext(fontPath)[1]
         if ext.lower() in [".otf", ".ttf", ".ttc"]:
             fontName = self.installFont(fontPath)
         else:
             raise DrawBotError("Font '%s' is not .ttf, .otf or .ttc." %
                                fontPath)
     return fontName
    def lineDash(self, *value):
        """
        Set a line dash with any given amount of lenghts.
        Uneven lenghts will have a visible stroke, even lenghts will be invisible.

        .. showcode:: /../examples/lineDash.py
        """
        if not value:
            raise DrawBotError("lineDash must be a list of dashes or None")
        if isinstance(value[0], (list, tuple)):
            value = value[0]
        self._addInstruction("lineDash", value)
    def fallbackFont(self, fontName):
        """
        Set a fallback font, this is used whenever a glyph is not available in the current font.

        ::

            fallbackFont("Times")
        """
        fontName = fontName.encode("ascii", "ignore")
        dummyFont = AppKit.NSFont.fontWithName_size_(fontName, 10)
        if dummyFont is None:
            raise DrawBotError("Fallback font '%s' is not available" %
                               fontName)
        self._dummyContext.fallbackFont(fontName)
        self._addInstruction("fallbackFont", fontName)
    def blendMode(self, operation):
        """
        Set a blend mode.

        Available operations are: `normal`, `multiply`, `screen`, `overlay`,
        `darken`, `lighten`, `colorDodge`, `colorBurn`, `softLight`,
        `hardLight`, `difference`, `exclusion`, `hue`, `saturation`,
        `color`, `luminosity`, `clear`, `copy`, `sourceIn`, `sourceOut`,
        `sourceAtop`, `destinationOver`, `destinationIn`, `destinationOut`,
        `destinationAtop`, `xOR`, `plusDarker` and `plusLighter`,

        .. showcode:: /../examples/blendMode.py
        """
        if operation not in self._dummyContext._blendModeMap.keys():
            raise DrawBotError(
                "blend mode must be %s" %
                (", ".join(self._dummyContext._blendModeMap.keys())))
        self._addInstruction("blendMode", operation)
    def imageSize(self, path, pageNumber=None):
        """
        Return the `width` and `height` of an image.

        .. showcode:: /../examples/imageSize.py
        """
        if isinstance(path, self._imageClass):
            path = path._nsImage()
        if isinstance(path, AppKit.NSImage):
            rep = path.TIFFRepresentation()
            _isPDF = False
        else:
            if isinstance(path, (str, unicode)):
                path = optimizePath(path)
            if path.startswith("http"):
                url = AppKit.NSURL.URLWithString_(path)
            else:
                if not os.path.exists(path):
                    raise DrawBotError("Image does not exist")
                url = AppKit.NSURL.fileURLWithPath_(path)
            _isPDF, pdfDocument = isPDF(url)
            # check if the file is an .eps
            _isEPS, epsRep = isEPS(url)
            # check if the file is an .gif
            _isGIF, gifRep = isGIF(url)
            if _isEPS:
                _isPDF = True
                rep = epsRep
            elif _isGIF and pageNumber is not None:
                rep = gifTools.gifFrameAtIndex(url, pageNumber - 1)
            elif _isPDF and pageNumber is not None:
                page = pdfDocument.pageAtIndex_(pageNumber - 1)
                # this is probably not the fastest method...
                rep = AppKit.NSImage.alloc().initWithData_(
                    page.dataRepresentation())
            else:
                rep = AppKit.NSImageRep.imageRepWithContentsOfURL_(url)
        if _isPDF:
            w, h = rep.size()
        elif _isGIF:
            w, h = rep.size()
        else:
            w, h = rep.pixelsWide(), rep.pixelsHigh()
        return w, h
Example #9
0
def downloadCurrentVersion():
    """
    Download the current version (dmg) and mount it
    """
    path = "http://static.typemytype.com/drawBot/DrawBot.dmg"
    try:
        # download and mount
        cmds = ["hdiutil", "attach", "-plist", path]
        popen = subprocess.Popen(cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = popen.communicate()
        if popen.returncode != 0:
            raise DrawBotError("Mounting failed")
        output = plistlib.readPlistFromString(out)
        dmgPath = None
        for item in output["system-entities"]:
            if "mount-point" in item:
                dmgPath = item["mount-point"]
                break
        AppKit.NSWorkspace.sharedWorkspace().openFile_(dmgPath)
    except:
        print "Something went wrong while downloading %s" % path
        If the text overflows the rectangle, the overflowed text is returned.

        The default alignment is `left`.

        .. showcode:: /../examples/textBox.py
        """
        if isinstance(txt, (str, unicode)):
            try:
                txt = txt.decode("utf-8")
            except UnicodeEncodeError:
                pass
        if align is None:
            align = "left"
        elif align not in self._dummyContext._textAlignMap.keys():
            raise DrawBotError(
                "align must be %s" %
                (", ".join(self._dummyContext._textAlignMap.keys())))
        self._requiresNewFirstPage = True
        self._addInstruction("textBox", txt, (x, y, w, h), align)
        return self._dummyContext.clippedText(txt, (x, y, w, h), align)

    def textbox(self, txt, x, y, w, h, align=None):
        _deprecatedWarningLowercase("textbox(%s, (%s, %s, %s, %s), align=%s)" %
                                    (txt, x, y, y, w, align))
        self.textbox(txt, (x, y, w, h), align)

    _formattedStringClass = FormattedString

    def FormattedString(self, *args, **kwargs):
        """
        Return a string object that can handle text formatting.