예제 #1
0
    def show(self, screen, callback):
        if callback:
            assert callable(callback)

        if len(self.buttons) == 0:
            self.buttons.append('Dismiss')

        numButtons = len(self.buttons)

        totalButtonsWidth = (self.minimumButtonWidth + self.buttonPadding
                             ) * numButtons + self.buttonPadding
        width = max(totalButtonsWidth, self.minimumViewWidth)
        buttonWidth = floor((width - self.buttonPadding) / numButtons -
                            self.buttonPadding)

        alertView = titled.TitledView()
        alertView.caption = self.title

        alertView.frame = alertView.frameForContentFrame(
            core.Rect(0, 0, width, self.viewHeight))
        bounds = alertView.contentBounds()

        rect = core.Rect(bounds)
        rect.y += self.buttonHeight + self.buttonPadding
        rect.height -= self.buttonHeight + self.buttonPadding

        textView = label.Label(self.text, frame=rect)
        textView.fontAttributes = font.attributes(18)
        textView.align = label.ALIGN_CENTER
        textView.textColor = core.Color(0, 0, 0)
        textView.backgroundColor = core.Color(1, 1, 1)

        rect.origin = bounds.x, bounds.y
        rect.size = buttonWidth, self.buttonHeight
        rect.x += self.buttonPadding
        rect.y += self.buttonPadding

        print('bounds', bounds)
        print('rect', rect)

        tag = 0
        for txt in self.buttons:
            btn = button.Button(txt, frame=rect)
            btn.tag = tag
            tag += 1
            btn.addTarget(self, self._onButtonClick)
            alertView.addChild(btn)
            rect.x += self.buttonPadding + buttonWidth

        alertView.addChild(textView)

        self._modal = modal.Modal(alertView)
        self._modal.present(screen.frame, self._onModalCallback)
        self.callback = callback
예제 #2
0
파일: light.py 프로젝트: DKGL/DKDemo
 def __init__(self,
              type=TYPE_DIRECTIONAL,
              pos=core.Vector3(0, 1, 0),
              color=core.Color(1, 1, 1, 1)):
     core.Light.__init__(self, type, pos, color)
     self.constAttenuation = 1
     self.linearAttenuation = 0
     self.quadraticAttenuation = 0
예제 #3
0
파일: _textured.py 프로젝트: DKGL/DKDemo
 def __init__(self, renderer, texture, sampler=None, color=core.Color(1,1,1,1), blend=blendstate.defaultOpaque):
     self.vertices = array.array('f')
     self.renderer = renderer
     self.color = color
     self.blend = blend
     self.texture = texture
     self.sampler = sampler
     self.count = 0
예제 #4
0
def RenderTextBaseline(renderer,
                       font,
                       begin,
                       align,
                       color=core.Color(0, 0, 0),
                       blend=blendstate.defaultAlpha):
    cls = RenderTextClass(align)
    return cls(renderer, font, begin, color, blend)
예제 #5
0
파일: sprite.py 프로젝트: DKGL/DKDemo
    def render(self, renderer):
        rc = renderer.contextForTexturedRects(texture=None,
                                              blend=blendstate.defaultAlpha)
        self._render(rc, core.Matrix3(), core.Color(1, 1, 1, 1))

        if rc.texture:  # draw rectangles
            with rc:
                pass
예제 #6
0
class ItemStyle:

    indentationLevelWidth = 15
    expandIconSize = 12
    padding = 2

    topMargin = 1
    leftMargin = 4
    rightMargin = 1
    bottomMargin = 1

    fontAttributes = font.attributes(14, embolden=0)

    backgroundColor = None
    backgroundColorHighlighted = core.Color(1, 1, 0)
    backgroundColorActivated = core.Color(0.25, 0.25, 1.0)
    backgroundColorDisabled = core.Color(0.9, 0.9, 0.9)

    textColor = core.Color(0, 0, 0)
    textColorHighlighted = core.Color(0, 0, 0)
    textColorActivated = core.Color(1, 1, 1)
    textColorDisabled = core.Color(0.5, 0.5, 0.5)

    outlineColor = None
    outlineColorHighlighted = None
    outlineColorActivated = core.Color(0, 0, 0, 1)
    outlineColorDisabled = None

    backgroundColorBlend = blendstate.defaultOpaque

    arrowColor = core.Color(0.5, 0.5, 0.5)
    arrowColorActivated = core.Color(0.25, 0.25, 1.0)

    iconTransform = core.Matrix3()

    scaleFactor = view.DEFAULT_UI_SCALE

    def __init__(self):
        self.font = None
예제 #7
0
파일: blendstate.py 프로젝트: DKGL/DKDemo
 def create(cls, **kwargs):
     bs = cls()
     bs.srcBlendRGB = kwargs.get('srcBlendRGB', BLEND_MODE_ONE)
     bs.srcBlendAlpha = kwargs.get('srcBlendAlpha', BLEND_MODE_ONE)
     bs.dstBlendRGB = kwargs.get('dstBlendRGB', BLEND_MODE_ZERO)
     bs.dstBlendAlpha = kwargs.get('dstBlendAlpha', BLEND_MODE_ZERO)
     bs.blendFuncRGB = kwargs.get('blendFuncRGB', BLEND_FUNC_ADD)
     bs.blendFuncAlpha = kwargs.get('blendFuncAlpha', BLEND_FUNC_ADD)
     bs.colorWriteR = kwargs.get('colorWriteR', True)
     bs.colorWriteG = kwargs.get('colorWriteG', True)
     bs.colorWriteB = kwargs.get('colorWriteB', True)
     bs.colorWriteA = kwargs.get('colorWriteA', True)
     bs.constantColor = kwargs.get('constantColor', core.Color(0.0, 0.0, 0.0, 0.0))
     return bs
예제 #8
0
class Label(view.View):

    fontAttributes = font.attributes(12)

    textColor = core.Color(0.0, 0.0, 0.0)
    outlineColor = None
    textTransform = core.Matrix3()
    scaleToFit = False

    leftMargin = 0
    topMargin = 0
    rightMargin = 0
    bottomMargin = 0

    def __init__(self, text='', *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.text = str(text)
        self.align = ALIGN_CENTER
        self.linebreak = LINE_BREAK_TRUNCATING_TAIL

    def onLoaded(self):
        super().onLoaded()
        if not self.font:
            self.font = font.loadUIFont(self.fontAttributes, self.scaleFactor)

    def onUnload(self):
        self.font = None
        super().onUnload()

    def onRender(self, renderer):
        super().onRender(renderer)

        if self.font:
            bounds = self.contentBounds()
            bounds.x += self.leftMargin
            bounds.y += self.bottomMargin
            bounds.width -= self.leftMargin + self.rightMargin
            bounds.height -= self.topMargin + self.bottomMargin

            font.drawText(renderer,
                          bounds,
                          self.text,
                          self.font,
                          self.textColor,
                          self.outlineColor,
                          scaleToFit=self.scaleToFit,
                          align=self.align,
                          linebreak=self.linebreak,
                          blend=blendstate.defaultAlpha)
예제 #9
0
    def __init__(self,
                 renderer,
                 font,
                 begin,
                 color=core.Color(0, 0, 0),
                 blend=blendstate.defaultAlpha):
        self.renderer = renderer
        self.font = font
        self.color = color
        self.blend = blend
        self.lines = []
        self.line_begin = begin.x

        self.scaleFactor = _pixelScaleFactor(renderer)
        self.line_height = font.lineHeight() * self.scaleFactor[1]

        self.position = core.Point(begin)
예제 #10
0
파일: menu.py 프로젝트: DKGL/DKDemo
class ItemStyle:
    """
    item layout with icon
    | left-margin | checkbox | padding | icon | padding | text | text-margin | arrow or shortcut | right-margin |

    item layout without icon
    | left-margin | checkbox | padding | text | padding | arrow or shortcut | right-margin |

    separator horizontal/vertical layout
    | separator-margin | separator-line | separator-margin |

    """

    minimumHeight = 12
    minimumWidth = 48

    topMargin = 4
    bottomMargin = 4
    leftMargin = 2
    rightMargin = 4
    textMargin = 12

    checkmarkSize = 12
    imageSize = 12
    arrowSize = 9
    padding = 2

    separatorColor = core.Color(0.75, 0.75, 0.75)
    separatorMargin = 4
    separatorWidth = 1

    textColor = core.Color(0, 0, 0)
    textColorHighlighted = core.Color(1, 1, 1)
    textColorDisabled = core.Color(0.56, 0.56, 0.56)

    outlineColor = None
    outlineColorHighlighted = None
    outlineColorDisabled = None

    checkmarkColor = textColor
    checkmarkColorHighlighted = textColorHighlighted
    checkmarkColorDisabled = textColorDisabled

    arrowColor = core.Color(0.26, 0.26, 0.26)
    arrowColorHighlighted = core.Color(0.94, 0.94, 0.94)
    arrowColorDisabled = textColorDisabled

    def __init__(self):
        self.font = None
예제 #11
0
파일: sprite.py 프로젝트: DKGL/DKDemo
    def _render(self, rc, transform, color):
        if self.hidden:
            return
        cc = core.Color(self.diffuse[0] * color.r, self.diffuse[1] * color.g,
                        self.diffuse[2] * color.b, self.alpha[0] * color.a)
        if cc.a > 0.0:
            transform = self.transform * transform

            # get texture ids
            if self.texturePack:
                texIds = self._textureIdsForState[self.state]
                if len(texIds):
                    texIndex = round(self.textureIndex[0]) % len(texIds)
                    texKey = texIds[texIndex]
                    frame = self.texturePack.frames.get(texKey)
                else:
                    frame = self.texturePack.frames.get(self.name)

                if frame:
                    # draw other Sprites
                    if rc.texture != self.texturePack.texture or rc.color.argb32Value(
                    ) != cc.argb32Value():
                        if rc.texture:
                            with rc:
                                pass
                        rc.texture = self.texturePack.texture
                        rc.color = cc

                    # calculate texture frame.
                    rect = core.Rect(self.size[0] * frame.offset.x,
                                     self.size[1] * frame.offset.y,
                                     self.size[0] * frame.scale.width,
                                     self.size[1] * frame.scale.height)

                    rc.add(rect, transform, self.TEXTURE_RECT, frame.transform)

            for c in self.children:
                c._render(rc, transform, cc)
예제 #12
0
파일: _shape.py 프로젝트: DKGL/DKDemo
 def add(self, shape, transform, faceColor, edgeColor=core.Color(0.0, 0.0, 0.0)):
     co = core.CollisionObject()
     co.setCollisionShape(shape)
     co.setWorldTransform(transform)
     self.objects.append(co)
     self.colorTable[co] = (faceColor, edgeColor)
예제 #13
0
파일: textfield.py 프로젝트: DKGL/DKDemo
class TextField(textinput.TextInput, control.Control, view.View):

    borderWidth = 1

    caretBlinkInterval = 0.5
    caretWidth = 1

    caretColor = core.Color(0.0, 0.0, 0.0)
    caretColorComposition = core.Color(0.0, 0.0, 0.75)

    selectionColor = core.Color(0.5, 0.5, 1.0)
    selectionColorInactivated = core.Color(0.6, 0.6, 1.0)
    selectionColorDisabled = core.Color(1.0, 0.0, 0.0)

    textColor = core.Color(0.0, 0.0, 0.0)
    textColorInactivated = core.Color(0.3, 0.3, 0.3)
    textColorDisabled = core.Color(0.4, 0.4, 0.4)

    textColorSelected = core.Color(1.0, 1.0, 1.0)
    textColorSelectedInactivated = core.Color(0.9, 0.9, 0.9)
    textColorSelectedDisabled = core.Color(0.4, 0.4, 1.0)

    textColorComposition = core.Color(0.0, 0.0, 0.5)
    textColorCompositionUnderCaret = core.Color(1.0, 1.0, 1.0)

    outlineColor = None
    outlineColorInactivated = None
    outlineColorDisabled = None

    outlineColorSelected = None
    outlineColorSelectedInactivated = None
    outlineColorSelectedDisabled = None

    outlineColorComposition = None
    outlineColorCompositionUnderCaret = None

    backgroundColor = core.Color(1.0, 1.0, 1.0)
    backgroundColorDisabled = core.Color(0.6, 0.6, 0.6)

    fontAttributes = font.attributes(14,
                                     kerning=False,
                                     file='SeoulNamsanM.ttf')

    keyboardId = 0
    acceptTab = False
    tabSpace = 4

    keyPressingDelay = 0.3
    keyRepeatInterval = 0.04

    def __init__(self, text='', *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__text = text
        self.__caretPos = 0
        self.__selectionBegin = -1  # selection: from __selectionBegin to __caretPos
        self.__timer = core.Timer()
        self.__editing = False
        self.__caretVisible = False
        self.__capturedMouseId = None
        self.__unmodifiedText = ''

    @property
    def text(self):
        return self.__text

    @text.setter
    def text(self, value):
        self.__text = value
        self.caretPos = self.__caretPos

    @property
    def caretPos(self):
        return self.__caretPos

    @caretPos.setter
    def caretPos(self, value):
        value = max(int(value), 0)
        if self.__caretPos != value:
            print('setCaretPos:', value)
            self.__caretPos = value
            tl = len(self.__text)
            if self.__caretPos > tl:
                self.__caretPos = tl
            self.__selectionBegin = -1
            if self.enabled:
                self.__caretVisible = True
                self.__timer.reset()
            self.updateScroll()
            self.redraw()

    @property
    def editing(self):
        return self.__editing

    @editing.setter
    def editing(self, value):
        b = bool(value)
        if self.__editing != b:
            self.__editing = b
            if self.__editing:
                self.captureKeyboard(self.keyboardId)
                self.screen().window.setTextInputEnabled(self.keyboardId, True)
                self.__caretVisible = True
                self.__unmodifiedText = self.__text
                print('textfield:{} capture keyboard:{}'.format(
                    id(self), self.keyboardId))
            else:
                self.screen().window.setTextInputEnabled(
                    self.keyboardId, False)
                self.releaseKeyboard(self.keyboardId)
                self.__caretVisible = False
                self.__unmodifiedText = ''
                print('textfield:{} release keyboard:{}'.format(
                    id(self), self.keyboardId))
            self.__timer.reset()
            self.redraw()

    def selectionRange(self):
        if self.__selectionBegin >= 0 and self.__selectionBegin != self.__caretPos:
            if self.__selectionBegin > self.__caretPos:
                return self.__caretPos, self.__selectionBegin
            else:
                return self.__selectionBegin, self.__caretPos
        return self.__caretPos, self.__caretPos

    def onLoaded(self):
        super().onLoaded()
        self.minimumViewHeight = self.font.lineHeight() / self.scaleFactor
        self.updateScroll()

    def onUnload(self):
        super().onUnload()

    def onResized(self):
        super().onResized()
        self.updateScroll()

    def onUpdate(self, delta, tick, date):
        super().onUpdate(delta, tick, date)
        if self.__editing and self.enabled:
            if self.__timer.elapsed() > self.caretBlinkInterval:
                self.__caretVisible = not self.__caretVisible
                self.__timer.reset()
                self.redraw()

    def characterIndexAtPosition(self, pos):
        bounds = self.contentBounds()
        x = pos.x - bounds.x
        invScale = 1.0 / self.scaleFactor
        lineWidth = lambda s: self.font.lineWidth(s) * invScale

        if x <= 0:
            return 0
        if x >= lineWidth(self.text):
            return len(self.text)

        width = 0
        width2 = 0
        index = 0
        while width < x:
            width2 = width
            index += 1
            width = lineWidth(self.text[0:index])

        if abs(x - width2) < abs(x - width):
            return index - 1
        return index

    def updateScroll(self):
        bounds = self.contentBounds()
        if self.font:
            invScale = 1.0 / self.scaleFactor
            charWidth = self.font.width * invScale

            if bounds.width > charWidth * 2:  # at least 2 characters should be displayed.
                maxX = bounds.width * 0.9
                minX = bounds.width * 0.1
                text = self.__text + self.composingText
                textLen = self.font.lineWidth(text) * invScale
                if textLen > maxX:
                    text = self.__text[0:self.__caretPos] + self.composingText
                    textLen = self.font.lineWidth(text) * invScale

                    transform = core.AffineTransform2(
                        core.Matrix3(self.contentTransform))
                    textLen += transform.translation[0]

                    indent = min(bounds.width * 0.1, charWidth)
                    offset = 0

                    while textLen < minX:
                        textLen += indent
                        offset += indent

                    while textLen > maxX:
                        textLen -= indent
                        offset -= indent

                    if offset != 0:
                        transform.translate(core.Vector2(offset, 0))
                        pos = transform.translation
                        if pos[0] > 0:
                            transform.translation = 0, pos[1]
                        self.contentTransform = transform.matrix3()
                    return
        self.contentTransform = core.Matrix3()

    def onRender(self, renderer):

        invScale = 1.0 / self.scaleFactor

        bounds = self.contentBounds()
        height = self.font.lineHeight() * invScale

        offsetX = bounds.x
        offsetY = int(bounds.y + (bounds.height - height) * 0.5)

        lineWidth = lambda text: self.font.lineWidth(text) * invScale

        drawText = lambda rect, text, tc, oc: \
            font.drawText(renderer, rect, text, self.font, tc, oc, align=font.ALIGN_BOTTOM_LEFT, linebreak=font.LINE_BREAK_CLIPPING)

        if self.enabled:
            super().onRender(renderer)
            if self.isKeyboardCapturedBySelf(self.keyboardId):  # activated
                textColor = self.textColor
                outlineColor = self.outlineColor
                textColorSelected = self.textColorSelected
                outlineColorSelected = self.outlineColorSelected
                selectionColor = self.selectionColor
            else:
                textColor = self.textColorInactivated
                outlineColor = self.outlineColorInactivated
                textColorSelected = self.textColorSelectedInactivated
                outlineColorSelected = self.outlineColorSelectedInactivated
                selectionColor = self.selectionColorInactivated
        else:  # disabled
            tmp = self.backgroundColor
            self.backgroundColor = self.backgroundColorDisabled
            super().onRender(renderer)
            self.backgroundColor = tmp
            self.__caretVisible = False
            textColor = self.textColorDisabled
            outlineColor = self.outlineColorDisabled
            textColorSelected = self.textColorSelectedDisabled
            outlineColorSelected = self.outlineColorSelectedDisabled
            selectionColor = self.selectionColorDisabled

        selectionRange = self.selectionRange()
        if selectionRange[0] != selectionRange[1]:
            left = self.__text[0:selectionRange[0]]
            right = self.__text[selectionRange[1]:]
        else:
            left = self.__text[0:self.__caretPos]
            right = self.__text[self.__caretPos:]

        width = lineWidth(left)
        rc = core.Rect(offsetX, offsetY, width, height)
        drawText(rc, left, textColor, outlineColor)
        offsetX += width

        if selectionRange[0] != selectionRange[1]:
            text = self.__text[selectionRange[0]:selectionRange[1]]
            width = lineWidth(text)
            rc = core.Rect(offsetX, offsetY, width, height)
            with renderer.contextForSolidRects(selectionColor) as r:
                r.add(rc)
            drawText(rc, text, textColorSelected, outlineColorSelected)

            if self.__caretVisible:
                if self.__caretPos > self.__selectionBegin:
                    rc = core.Rect(offsetX + width, offsetY, self.caretWidth,
                                   height)
                else:
                    rc = core.Rect(offsetX, offsetY, self.caretWidth, height)
                with renderer.contextForSolidRects(self.caretColor) as r:
                    r.add(rc)
            offsetX += width

        else:
            if len(self.composingText) > 0:
                width = lineWidth(self.composingText)
                rc = core.Rect(offsetX, offsetY, width, height)
                if self.__caretVisible:
                    with renderer.contextForSolidRects(
                            self.caretColorComposition) as r:
                        r.add(rc)
                    drawText(rc, self.composingText,
                             self.textColorCompositionUnderCaret,
                             self.outlineColorCompositionUnderCaret)
                else:
                    drawText(rc, self.composingText, self.textColorComposition,
                             self.outlineColorComposition)

                offsetX += width
            else:
                if self.__caretVisible:
                    rc = core.Rect(offsetX, offsetY, self.caretWidth, height)
                    with renderer.contextForSolidRects(self.caretColor) as r:
                        r.add(rc)

        width = lineWidth(right)
        rc = core.Rect(offsetX, offsetY, width, height)
        drawText(rc, right, textColor, outlineColor)

    def onMouseDown(self, deviceId, buttonId, pos):
        editing = self.__editing
        selectionRange = self.selectionRange()

        self.editing = True

        if self.__capturedMouseId is None and buttonId == 0:
            if editing or selectionRange[0] == selectionRange[1]:
                self.captureMouse(deviceId)
                index = self.characterIndexAtPosition(pos)
                self.__capturedMouseId = deviceId
                self.caretPos = index
                self.redraw()

        return super().onMouseDown(deviceId, buttonId, pos)

    def onMouseUp(self, deviceId, buttonId, pos):
        if buttonId == 0 and self.__capturedMouseId == deviceId:
            self.__capturedMouseId = None
            if self.__selectionBegin == self.__caretPos:
                self.__selectionBegin = -1

        self.releaseMouse(deviceId)
        return super().onMouseUp(deviceId, buttonId, pos)

    def onMouseMove(self, deviceId, pos, delta):
        if self.__capturedMouseId == deviceId:
            index = self.characterIndexAtPosition(pos)
            if self.__selectionBegin < 0:
                self.__selectionBegin = self.__caretPos
            self.__caretPos = index
            self.updateScroll()
            self.redraw()

        return super().onMouseMove(deviceId, pos, delta)

    def onMouseLost(self, deviceId):
        self.__capturedMouseId = None
        return super().onMouseLost(deviceId)

    def onKeyboardLost(self, deviceId):
        print('textfield:{}.onKeyboardLost:{}'.format(id(self), deviceId))
        self.editing = False
        return super().onKeyboardLost(deviceId)

    def moveLeft(self):
        if self.shiftDown:
            if self.__selectionBegin < 0:
                self.__selectionBegin = self.__caretPos
            self.__caretPos = max(self.__caretPos - 1, 0)
        else:
            range = self.selectionRange()
            if range[0] == range[1]:
                self.__caretPos = max(self.__caretPos - 1, 0)
            else:
                self.__caretPos = range[0]
            self.__selectionBegin = -1
        self.__caretVisible = True
        self.__timer.reset()
        self.updateScroll()
        self.redraw()

    def moveToBeginningOfLine(self):
        if self.shiftDown:
            if self.__selectionBegin < 0:
                self.__selectionBegin = self.__caretPos
            self.__caretPos = 0
        else:
            self.__caretPos = 0
            self.__selectionBegin = -1
        self.__caretVisible = True
        self.__timer.reset()
        self.updateScroll()
        self.redraw()

    def moveRight(self):
        if self.shiftDown:
            if self.__selectionBegin < 0:
                self.__selectionBegin = self.__caretPos
            self.__caretPos = min(len(self.__text), self.__caretPos + 1)
        else:
            range = self.selectionRange()
            if range[0] == range[1]:
                self.__caretPos = min(len(self.__text), self.__caretPos + 1)
            else:
                self.__caretPos = range[1]
            self.__selectionBegin = -1
        self.__caretVisible = True
        self.__timer.reset()
        self.updateScroll()
        self.redraw()

    def moveToEndOfLine(self):
        super().moveToEndOfLine()
        if self.shiftDown:
            if self.__selectionBegin < 0:
                self.__selectionBegin = self.__caretPos
            self.__caretPos = len(self.__text)
        else:
            self.__caretPos = len(self.__text)
            self.__selectionBegin = -1
        self.__caretVisible = True
        self.__timer.reset()
        self.updateScroll()
        self.redraw()

    def insertText(self, text):
        range = self.selectionRange()
        left = self.__text[0:range[0]]
        right = self.__text[range[1]:]
        if range[0] == range[1]:
            self.__text = left + text + right
            self.__caretPos += len(text)
        else:
            self.__text = left + text
            self.__caretPos = len(self.text)
            self.text += right
        self.__selectionBegin = -1
        self.__caretVisible = True
        self.__timer.reset()
        self.updateScroll()
        self.redraw()

    def setCompositionText(self, text):
        range = self.selectionRange()
        if range[0] != range[1]:
            left = self.__text[0:range[0]]
            right = self.__text[range[1]:]
            self.__text = left + right
        self.__selectionBegin = -1
        self.__caretVisible = True
        self.__timer.reset()
        self.updateScroll()
        self.redraw()

    def deleteBackward(self):
        range = self.selectionRange()
        if range[0] == range[1]:
            if range[0] > 0:
                left = self.__text[0:range[0] - 1]
                right = self.__text[range[1]:]
                self.__text = left + right
                self.__caretPos -= 1
        else:
            left = self.__text[0:range[0]]
            right = self.__text[range[1]:]
            self.__text = left + right
            self.__caretPos = range[0]
        self.__selectionBegin = -1
        self.__caretVisible = True
        self.__timer.reset()
        self.updateScroll()
        self.redraw()

    def deleteForward(self):
        range = self.selectionRange()
        if range[0] == range[1]:
            if range[1] < len(self.__text):
                left = self.__text[0:range[0]]
                right = self.__text[range[1] + 1:]
                self.__text = left + right
        else:
            left = self.__text[0:range[0]]
            right = self.__text[range[1]:]
            self.__text = left + right
            self.__caretPos = range[0]
        self.__selectionBegin = -1
        self.__caretVisible = True
        self.__timer.reset()
        self.updateScroll()
        self.redraw()

    def processEscape(self):
        if self.editing:
            self.__text = self.__unmodifiedText
            self.__caretPos = 0
            self.__selectionBegin = -1
            self.editing = False
            self.updateScroll()
            # post notification
            print('User cancelled editing. (post notification)')

    def processCarriageReturn(self):
        if self.editing:
            self.__caretPos = 0
            self.__selectionBegin = -1
            self.editing = False
            self.updateScroll()
            # post notification!
            print('User finish editing. (post notification)')

    def processLineFeed(self):
        self.processCarriageReturn()

    def insertTab(self):
        self.processCarriageReturn()
예제 #14
0
class RadioButton(control.Control, view.View):

    radius = 8
    circleBorder = 1
    innerCircleRadius = 5

    leftMargin = 4
    rightMargin = 0
    padding = 8

    circleBorderColor = core.Color(0.4, 0.4, 0.4)

    circleColor = core.Color(0.9, 0.9, 1.0)
    circleColorHighlighted = core.Color(0.8, 0.8, 1.0)
    circleColorActivated = core.Color(0.6, 0.6, 1.0)
    circleColorDisabled = core.Color(0.6, 0.6, 0.6)

    innerCircleColor = core.Color(0.25, 0.25, 0.25)
    innerCircleColorHighlighted = core.Color(0.25, 0.25, 1.0)
    innerCircleColorActivated = core.Color(0.0, 0.0, 0.6)
    innerCircleColorDisabled = core.Color(0.2, 0.2, 0.2)

    textColor = core.Color(0.0, 0.0, 0.0)
    textColorHighlighted = core.Color(0.0, 0.0, 0.0)
    textColorActivated = core.Color(0.0, 0.0, 0.7)
    textColorDisabled = core.Color(0.3, 0.3, 0.3)

    outlineColor = None
    outlineColorHighlighted = None
    outlineColorActivated = None
    outlineColorDisabled = None

    backgroundColor = core.Color(1, 1, 1)

    fontAttributes = font.attributes(14)

    interactOnlyInsideVisibleContentRect = True

    minimumViewWidth = (radius + circleBorder) * 2
    minimumViewHeight = (radius + circleBorder) * 2

    def __init__(self, text, group, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.text = str(text)
        self.group = group
        self.__selected = False
        self.__mouseHover = False
        self.__activated = False
        self.__capturedMouseId = None
        self.__interactFrame = None

    def onLoaded(self):
        super().onLoaded()

    def onUnload(self):
        super().onUnload()

    def onRender(self, renderer):
        super().onRender(renderer)

        state = self.STATE_DISABLED if not self.enabled else \
                self.STATE_ACTIVATED if self.__activated else \
                self.STATE_HIGHLIGHTED if self.__mouseHover else \
                self.STATE_NORMAL

        bounds = self.contentBounds()

        # draw circle
        circleRect = core.Rect(bounds.x + self.circleBorder + self.leftMargin,
                               bounds.y + bounds.height * 0.5 - self.radius,
                               self.radius * 2, self.radius * 2)
        circleRect.x = math.floor(
            circleRect.x * self.scaleFactor) / self.scaleFactor
        circleRect.y = math.floor(
            circleRect.y * self.scaleFactor) / self.scaleFactor

        if self.circleBorder > 0:
            rc = core.Rect(circleRect)
            rc.origin = rc.x - self.circleBorder, rc.y - self.circleBorder
            rc.size = rc.width + self.circleBorder * 2, rc.height + self.circleBorder * 2
            with renderer.contextForSolidEllipses(self.circleBorderColor) as r:
                r.add(rc)

        circleColor = (self.circleColor, self.circleColorHighlighted,
                       self.circleColorActivated,
                       self.circleColorDisabled)[state]

        with renderer.contextForSolidEllipses(circleColor) as r:
            r.add(circleRect)

        if self.__selected:
            r = self.radius - self.innerCircleRadius
            innerCircleRect = core.Rect(circleRect.x + r, circleRect.y + r,
                                        self.innerCircleRadius * 2,
                                        self.innerCircleRadius * 2)

            innerCircleColor = (self.innerCircleColor,
                                self.innerCircleColorHighlighted,
                                self.innerCircleColorActivated,
                                self.innerCircleColorDisabled)[state]

            with renderer.contextForSolidEllipses(
                    innerCircleColor, blend=blendstate.defaultOpaque) as r:
                r.add(innerCircleRect)

        # draw text
        textRect = core.Rect(
            circleRect.x + circleRect.width + self.circleBorder + self.padding,
            bounds.y, 0, bounds.height)

        lineWidth = self.font.lineWidth(self.text)
        lineHeight = self.font.lineHeight()
        textRect.width = min(
            bounds.x + bounds.width - textRect.x - self.rightMargin, lineWidth)

        # with renderer.contextForSolidRects(core.Color(1,0,0), blend=blendstate.defaultOpaque) as r:
        #     r.add(textRect)

        textColor = (self.textColor, self.textColorHighlighted,
                     self.textColorActivated, self.textColorDisabled)[state]
        outlineColor = (self.outlineColor, self.outlineColorHighlighted,
                        self.outlineColorActivated,
                        self.outlineColorDisabled)[state]

        font.drawText(renderer,
                      textRect,
                      self.text,
                      self.font,
                      textColor,
                      outlineColor,
                      align=font.ALIGN_LEFT,
                      linebreak=font.LINE_BREAK_TRUNCATING_TAIL,
                      blend=blendstate.defaultAlpha)

        if self.interactOnlyInsideVisibleContentRect:
            x1 = circleRect.x - self.circleBorder - self.padding
            x2 = textRect.x + textRect.width + self.padding

            textOriginY = bounds.y + (bounds.height - lineHeight) * 0.5
            y1 = min(circleRect.y - self.circleBorder,
                     textOriginY) - self.padding
            y2 = max(circleRect.y + circleRect.height,
                     textOriginY + lineHeight) + self.padding

            self.__interactFrame = core.Rect(x1, y1, x2 - x1, y2 - y1)
        else:
            self.__interactFrame = bounds

    def onMouseDown(self, deviceId, buttonId, pos):
        super().onMouseDown(deviceId, buttonId, pos)
        if self.__capturedMouseId:
            if not self.isMouseCapturedBySelf(self.__capturedMouseId[0]):
                self.__capturedMouseId = None

        if self.__capturedMouseId is None:
            if self.__interactFrame and self.__interactFrame.isInside(pos):
                self.captureMouse(deviceId)
                self.__capturedMouseId = (deviceId, buttonId)
                self.__activated = True
                self.redraw()

    def onMouseUp(self, deviceId, buttonId, pos):
        super().onMouseUp(deviceId, buttonId, pos)
        if self.__capturedMouseId and self.__capturedMouseId == (deviceId,
                                                                 buttonId):
            self.releaseMouse(deviceId)
            if self.__interactFrame and self.__interactFrame.isInside(pos):
                self.setSelected()

            self.__capturedMouseId = None
            self.__activated = False
            self.redraw()

    def onMouseMove(self, deviceId, pos, delta):
        super().onMouseMove(deviceId, pos, delta)
        if self.__capturedMouseId and self.__capturedMouseId[0] == deviceId:
            act = self.__activated
            if self.isMouseCapturedBySelf(deviceId):
                if self.__interactFrame:
                    self.__activated = self.__interactFrame.isInside(pos)
                else:
                    self.__activated = False
            else:
                self.__capturedMouseId = None
                self.__activated = False

            if act != self.__activated:
                self.redraw()

        elif deviceId == 0:
            h = self.__mouseHover
            self.__mouseHover = self.__interactFrame.isInside(
                pos) if self.__interactFrame else False
            if self.__mouseHover != h:
                self.redraw()

    def onMouseLeave(self, deviceId):
        super().onMouseLeave(deviceId)
        if deviceId == 0 and self.__mouseHover:
            self.__mouseHover = False
            self.redraw()

    def siblings(self):
        parent = self.parent()
        s = []
        if parent and self.group is not None:
            for c in parent.children():
                if c is not self and isinstance(c, RadioButton):
                    if c.group == self.group:
                        s.append(c)
        return s

    @property
    def selected(self):
        return self.__selected

    def setSelected(self):
        if not self.__selected:
            self.__selected = True
            parent = self.parent()
            if parent and self.group is not None:
                for c in parent.children():
                    if c is not self and isinstance(c, RadioButton):
                        if c.group == self.group:
                            if c.__selected:
                                c.__selected = False
                                c.redraw()
            self.redraw()
            # post event
            screen = self.screen()
            if screen:
                screen.postOperation(self.postEvent, ())

    def postEvent(self):
        super().invokeAllTargets(self)
예제 #15
0
파일: progress.py 프로젝트: DKGL/DKDemo
    def onRender(self, renderer):
        border = round(self.borderWidth)
        border2 = border * 2
        bounds = self.contentBounds()

        clearColor = core.Color(0.0, 0.0, 0.0, 0.0)

        renderer.clear(clearColor)

        size = math.floor(min(bounds.width, bounds.height))

        circleRect = core.Rect(0, 0, size, size)
        circleRect.center = bounds.center

        if border > 0:
            with renderer.contextForSolidEllipses(
                    self.borderColor, blend=blendstate.defaultOpaque) as r:
                r.add(circleRect)
            size -= border2
            circleRect.size = size, size
            circleRect.origin = circleRect.x + border, circleRect.y + border

        if size > 0:
            if self.__csLayerMask is None:
                rt = rendertarget.RenderTarget(size * self.scaleFactor,
                                               size * self.scaleFactor,
                                               rendertarget.DEPTH_NONE)
                rd = Renderer(rt)
                rd.clear(core.Color(0.0, 0.0, 0.0, 0.0))
                with rd.contextForSolidEllipses(
                        core.Color(1, 1, 1,
                                   1), blend=blendstate.defaultOpaque) as r:
                    r.add(core.Rect(0, 0, 1, 1))
                self.__csLayerMask = rt.colorTextureAtIndex(0)

            prog = self._progress / (self.maximumValue - self.minimumValue)
            if prog < 0.0: prog = 0.0
            if prog > 1.0: prog = 1.0

            if prog <= 0.0:
                with renderer.contextForSolidEllipses(
                        self.backgroundColor,
                        blend=blendstate.defaultOpaque) as r:
                    r.add(circleRect)
            elif prog >= 1.0:
                with renderer.contextForSolidEllipses(
                        self.progressColor,
                        blend=blendstate.defaultOpaque) as r:
                    r.add(circleRect)
            else:

                prog *= math.pi * 2
                normalizedCircularPos = core.Point(
                    math.sin(prog) * 0.5 + 0.5,
                    math.cos(prog) * 0.5 + 0.5)  # 0.0~1.0

                texSize = self.__csLayerMask.width / self.scaleFactor, self.__csLayerMask.height / self.scaleFactor
                offset = round(circleRect.x +
                               (circleRect.width - texSize[0]) * 0.5), round(
                                   circleRect.y +
                                   (circleRect.height - texSize[1]) * 0.5)

                with renderer.contextForSolidEllipses(
                        self.backgroundColor,
                        blend=blendstate.defaultOpaque) as r:
                    r.add(circleRect)

                with renderer.contextForTexturedTriangleFan(
                        self.__csLayerMask,
                        color=self.progressColor,
                        blend=blendstate.defaultAlpha) as r:

                    _pt1 = core.Point()
                    _pt2 = core.Point()

                    def addTexPos(x, y):
                        _pt1.tuple = x * texSize[0] + offset[
                            0], y * texSize[1] + offset[1]
                        _pt2.tuple = x, y
                        r.add(_pt1, _pt2)

                    addTexPos(0.5, 0.5)
                    addTexPos(0.5, 1.0)

                    if prog < math.pi * 0.5:
                        addTexPos(normalizedCircularPos.x, 1.0)
                        addTexPos(normalizedCircularPos.x,
                                  normalizedCircularPos.y)
                    else:
                        addTexPos(1.0, 1.0)
                        addTexPos(1.0, 0.5)
                        if prog < math.pi:
                            addTexPos(1.0, normalizedCircularPos.y)
                            addTexPos(normalizedCircularPos.x,
                                      normalizedCircularPos.y)
                        else:
                            addTexPos(1.0, 0.0)
                            addTexPos(0.5, 0.0)
                            if prog < math.pi * 1.5:
                                addTexPos(normalizedCircularPos.x, 0.0)
                                addTexPos(normalizedCircularPos.x,
                                          normalizedCircularPos.y)
                            else:
                                addTexPos(0.0, 0.0)
                                addTexPos(0.0, 0.5)
                                if prog < math.pi * 2.0:
                                    addTexPos(0.0, normalizedCircularPos.y)
                                    addTexPos(normalizedCircularPos.x,
                                              normalizedCircularPos.y)

            innerCircleSize = math.floor(
                min(self.innerCircleRadius * 2, size - border2))
            if innerCircleSize > 0:

                innerCircleRect = core.Rect(0, 0, innerCircleSize,
                                            innerCircleSize)
                innerCircleRect.center = bounds.center

                if border > 0:
                    with renderer.contextForSolidEllipses(
                            self.borderColor,
                            blend=blendstate.defaultOpaque) as r:
                        r.add(innerCircleRect)

                    innerCircleRect.origin = innerCircleRect.x + border, innerCircleRect.y + border
                    innerCircleRect.size = innerCircleRect.width - border2, innerCircleRect.height - border2
                    innerCircleSize -= border2

                if innerCircleSize > 0:
                    with renderer.contextForSolidEllipses(
                            clearColor, blend=blendstate.defaultOpaque) as r:
                        r.add(innerCircleRect)
예제 #16
0
파일: progress.py 프로젝트: DKGL/DKDemo
class AnimatedProgressView(view.View):

    progressAnimation = 0.5

    borderWidth = 1
    borderColor = core.Color(0.0, 0.0, 0.0)

    backgroundColor = core.Color(0.5, 0.5, 0.5)
    progressColor = core.Color(1.0, 1.0, 1.0)

    minimumViewHeight = borderWidth * 2 + 1
    minimumViewWidth = borderWidth * 2 + 1

    def __init__(self,
                 initialValue=0.0,
                 minValue=0.0,
                 maxValue=1.0,
                 *args,
                 **kwargs):
        super().__init__(*args, **kwargs)
        self._progress = initialValue
        self.minimumValue = minValue
        self.maximumValue = maxValue
        self.__animatedValue = None

    @property
    def progress(self):
        if self.__animatedValue:
            return self.__animatedValue.end
        return self._progress

    def setProgress(self, value, animate=True):

        if value < self.minimumValue: value = self.minimumValue
        elif value > self.maximumValue: value = self.maximumValue

        if self._progress != value and animate and self.progressAnimation > 0.0:
            anim = _AnimatedProgressValue()
            anim.begin = self._progress
            anim.end = value
            anim.length = self.progressAnimation
            anim.elapsed = 0.0
            self.__animatedValue = anim
        else:
            self._progress = value
            self.__animatedValue = None

    def onUnload(self):
        super().onUnload()
        self._progress = self.progress
        self.__animatedValue = None

    def onUpdate(self, delta, tick, date):
        super().onUpdate(delta, tick, date)
        if self.__animatedValue:
            if self.__animatedValue.length > 0.0:
                self.__animatedValue.elapsed += delta
                t = self.__animatedValue.elapsed / self.__animatedValue.length
                t1 = 0 if t < 0.0 else 1.0 if t > 1.0 else t
                t2 = 1.0 - t1
                value = self.__animatedValue.end * t1 + self.__animatedValue.begin * t2
                if value < self.minimumValue: value = self.minimumValue
                elif value > self.maximumValue: value = self.maximumValue
                self._progress = value
                if self.__animatedValue.elapsed >= self.__animatedValue.length:
                    self.__animatedValue = None
            else:
                value = self.__animatedValue.end
                if value < self.minimumValue: value = self.minimumValue
                elif value > self.maximumValue: value = self.maximumValue
                self._progress = value
                self.__animatedValue = None
            self.redraw()

    def onRender(self, renderer):
        border = round(self.borderWidth)
        border2 = border * 2
        bounds = self.bounds()

        rc = core.Rect(bounds.x + border, bounds.y + border,
                       bounds.width - border2, bounds.height - border2)
        prog = self._progress / (self.maximumValue - self.minimumValue)
        if prog < 0.0: prog = 0.0
        if prog > 1.0: prog = 1.0
        rc.width = rc.width * prog

        if border > 0:
            renderer.clear(self.borderColor)
            with renderer.contextForSolidRects(
                    self.progressColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

            rc.x += rc.width
            rc.width = (bounds.width - border2) - rc.width

            with renderer.contextForSolidRects(
                    self.backgroundColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

        else:
            renderer.clear(self.backgroundColor)
            with renderer.contextForSolidRects(
                    self.progressColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)
예제 #17
0
파일: button.py 프로젝트: DKGL/DKDemo
class Button(label.Label, control.Control, imageview.ImageView):

    fontAttributes = font.attributes(12)

    backgroundColor = core.Color(0.85, 0.85, 0.85)
    backgroundColorHighlighted = core.Color(0.9, 0.9, 1.0)
    backgroundColorActivated = core.Color(0.5, 0.5, 0.5)
    backgroundColorDisabled = core.Color(0.4, 0.4, 0.4)

    textColor = core.Color(0.0, 0.0, 0.0)
    textColorHighlighted = core.Color(0.0, 0.0, 0.0)
    textColorActivated = core.Color(1.0, 1.0, 1.0)
    textColorDisabled = core.Color(0.3, 0.3, 0.3)

    outlineColor = None
    outlineColorHighlighted = core.Color(1.0, 1.0, 1.0, 1.0)
    outlineColorActivated = core.Color(0.0, 0.0, 0.0, 1.0)
    outlineColorDisabled = None

    backgroundImage = None
    backgroundImageHighlighted = None
    backgroundImageActivated = None
    backgroundImageDisabled = None

    backgroundImageTransform = core.Matrix3()

    borderColor = core.Color(0.0, 0.0, 0.0, 1.0)
    borderWidth = 1


    def __init__(self, text='Button', *args, **kwargs):
        super().__init__(text=text, *args, **kwargs)

        self.buttonPressed = False
        self.__mouseHover = False
        self.__capturedMouseId = None
        if self.textureImage:
            self.backgroundImage = self.textureImage

    def setTextColor(self, color, state=control.Control.STATE_ALL):
        assert isinstance(color, core.Color)
        if state in (self.STATE_ALL, self.STATE_NORMAL):
            self.textColor = color
        if state in (self.STATE_ALL, self.STATE_HIGHLIGHTED):
            self.textColorHighlighted = color
        if state in (self.STATE_ALL, self.STATE_ACTIVATED):
            self.textColorActivated = color
        if state in (self.STATE_ALL, self.STATE_DISABLED):
            self.textColorDisabled = color

    def setOutlineColor(self, color, state=control.Control.STATE_ALL):
        assert isinstance(color, core.Color)
        if state in (self.STATE_ALL, self.STATE_NORMAL):
          self.outlineColor = color
        if state in (self.STATE_ALL, self.STATE_HIGHLIGHTED):
          self.outlineColorHighlighted = color
        if state in (self.STATE_ALL, self.STATE_ACTIVATED):
          self.outlineColorActivated = color
        if state in (self.STATE_ALL, self.STATE_DISABLED):
            self.outlineColorDisabled = color


    def onLoaded(self):
        super().onLoaded()


    def onUnload(self):
        self.backgroundImage = None
        self.backgroundImageHighlighted = None
        self.backgroundImageActivated = None
        self.backgroundImageDisabled = None
        return super().onUnload()

    def onRender(self, r):

        state = self.STATE_DISABLED if not self.enabled else \
                self.STATE_ACTIVATED if self.buttonPressed else \
                self.STATE_HIGHLIGHTED if self.__mouseHover else \
                self.STATE_NORMAL

        textColors = (self.textColor,
                      self.textColorHighlighted,
                      self.textColorActivated,
                      self.textColorDisabled)

        outlineColors = (self.outlineColor,
                         self.outlineColorHighlighted,
                         self.outlineColorActivated,
                         self.outlineColorDisabled)

        bgColors = (self.backgroundColor,
                    self.backgroundColorHighlighted,
                    self.backgroundColorActivated,
                    self.backgroundColorDisabled)

        bgImages = (self.backgroundImage,
                    self.backgroundImageHighlighted,
                    self.backgroundImageActivated,
                    self.backgroundImageDisabled)

        self.textColor = textColors[state]
        self.outlineColor = outlineColors[state]
        self.backgroundColor = bgColors[state]
        self.textureImage = bgImages[state]
        if not self.textureImage:
            self.textureImage = self.backgroundImage

        super().onRender(r)
        self.backgroundColor = bgColors[0]
        self.textColor = textColors[0]
        self.outlineColor = outlineColors[0]


    def discardAction(self):
        if self.__capturedMouseId:
            if self.isMouseCapturedBySelf(self.__capturedMouseId[0]):
                self.releaseMouse(self.__capturedMouseId[0])
            self.__capturedMouseId = None
            self.buttonPressed = False
            self.redraw()

    def onMouseDown(self, deviceId, buttonId, pos):
        super().onMouseDown(deviceId, buttonId, pos)
        acceptMouse = True
        if self.__capturedMouseId:
            if not self.isMouseCapturedBySelf(self.__capturedMouseId[0]):
                self.__capturedMouseId = None

        if self.__capturedMouseId is None:
            self.captureMouse(deviceId)
            self.__capturedMouseId = (deviceId, buttonId)
            self.buttonPressed = True
            self.redraw()

    def onMouseUp(self, deviceId, buttonId, pos):
        super().onMouseUp(deviceId, buttonId, pos)
        if self.__capturedMouseId and self.__capturedMouseId == (deviceId, buttonId):
            self.releaseMouse(deviceId)
            if self.bounds().isInside(pos):
                self.screen().postOperation(self.postEvent, ())

            self.__capturedMouseId = None
            self.buttonPressed = False
            self.redraw()

    def onMouseMove(self, deviceId, pos, delta):
        super().onMouseMove(deviceId, pos, delta)
        if self.__capturedMouseId and self.__capturedMouseId[0] == deviceId:
            btnPressed = self.buttonPressed
            if self.isMouseCapturedBySelf(deviceId):
                self.buttonPressed = self.bounds().isInside(pos)
            else:
                self.__capturedMouseId = None
                self.buttonPressed = False

            if btnPressed != self.buttonPressed:
                self.redraw()

        elif deviceId == 0:
            if not self.__mouseHover:
                self.__mouseHover = True
                if not self.buttonPressed:
                    self.redraw()

    def onMouseLeave(self, deviceId):
        super().onMouseLeave(deviceId)
        if deviceId == 0 and self.__mouseHover:
            self.__mouseHover = False
            if not self.buttonPressed:
                self.redraw()

    def postEvent(self):
        super().invokeAllTargets(self)
예제 #18
0
def drawText(renderer,
             frame,
             text,
             font,
             textColor=core.Color(1.0, 1.0, 1.0, 1.0),
             outlineColor=core.Color(0, 0, 0, 0.5),
             scaleToFit=False,
             align=ALIGN_CENTER,
             alignToPixel=True,
             linebreak=LINE_BREAK_TRUNCATING_TAIL,
             blend=blendstate.defaultAlpha):

    textFont = None
    outlineFont = None
    if font:
        if isinstance(font, UIFont):
            textFont = font.textFont
            outlineFont = font.outlineFont
        elif isinstance(font, core.Font):
            textFont = font
        elif isinstance(font, (tuple, list)):
            c = len(font)
            if c > 0:
                textFont = font[0]
            if c > 1:
                outlineFont = font[1]
        else:
            raise TypeError(
                'font argument must be Font or two Font objects tuple.')

    layoutFont = textFont if textFont else outlineFont

    if len(text) > 0 and frame.width > 0 and frame.height > 0 and layoutFont:

        viewport = renderer.viewport[2:]
        scale = renderer.bounds[2:]
        scaleFactor = (viewport[0] / scale[0], viewport[1] / scale[1])

        localToPixel = lambda x, y: (x * scaleFactor[0], y * scaleFactor[1])
        pixelToLocal = lambda x, y: (x / scaleFactor[0], y / scaleFactor[1])

        pixelFrame = core.Rect(frame)
        pixelFrame.origin = localToPixel(*frame.origin)
        pixelFrame.size = localToPixel(*frame.size)

        text = linebreak(pixelFrame, layoutFont, text)

        width = layoutFont.lineWidth(text)
        height = layoutFont.lineHeight()
        baseline = layoutFont.baseline

        if scaleToFit:
            scaleX = pixelFrame.width / width
            scaleY = pixelFrame.height / height
            scale = min(scaleX, scaleY)
            width = width * scale
            height = height * scale
            baseline = baseline * scale

        begin = align(pixelFrame, width, height, baseline)
        if alignToPixel:
            x = floor(begin[0] + 0.5)
            y = floor(begin[1] + 0.5)
            begin = (x, y)

        end = (begin[0] + width, begin[1])

        begin = core.Point(pixelToLocal(*begin))
        end = core.Point(pixelToLocal(*end))

        if outlineFont and outlineColor:
            renderer.renderTextBaseline(begin, end, text, outlineFont,
                                        outlineColor, blend)
        if textFont and textColor:
            renderer.renderTextBaseline(begin, end, text, textFont, textColor,
                                        blend)
예제 #19
0
 def onLoaded(self):
     super().onLoaded()
     self.setBlendState(blendstate.defaultAlpha)
     self.backgroundColor = core.Color(0, 0, 0, 0)
     self.screen().postOperation(self.setContentViewFrameToCenter, ())
예제 #20
0
파일: view.py 프로젝트: DKGL/DKDemo
class View(frame.Frame):

    fontAttributes = font.attributes(12)

    backgroundColor = core.Color(1.0, 1.0, 1.0)

    borderColor = core.Color(0.0, 0.0, 0.0, 1.0)
    borderWidth = 0

    minimumViewWidth = 1
    minimumViewHeight = 1

    def __init__(self, frame=core.Rect(0, 0, 1, 1), *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.scaleFactor = DEFAULT_UI_SCALE
        assert self.scaleFactor > 0
        assert isinstance(frame, core.Rect)

        self.layouter = None
        self.gestureRecognizers = []

        self.setFrame(frame)
        self.setBlendState(blendstate.defaultOpaque)
        self.font = None

    def layout(self):
        if self.layouter:
            self.layouter(self.contentBounds(), self.children())

    def onResized(self):
        self.contentScale = tuple(v / self.scaleFactor
                                  for v in self.contentResolution)
        self.surfaceVisibilityTest = not (round(self.borderWidth) > 0)
        self.layout()

    @property
    def frame(self):
        return core.Rect(self.__frame)

    @frame.setter
    def frame(self, frame):
        self.setFrame(frame)

    def setFrame(self, frame):
        assert isinstance(frame, core.Rect)
        #assert frame.width > 0
        #assert frame.height > 0
        assert self.minimumViewWidth > 0
        assert self.minimumViewHeight > 0
        width = max(frame.width, self.minimumViewWidth)
        height = max(frame.height, self.minimumViewHeight)

        frame = core.Rect(frame.origin + (width, height))

        try:
            f = self.__frame
            if f == frame:
                return
        except AttributeError:
            pass

        self.__frame = frame
        self.contentScale = width, height

        linear = core.LinearTransform2()
        linear.scale(width, height)
        self.transform = core.AffineTransform2(linear, frame.origin).matrix3()

    def bounds(self):
        '''
        :return: projected local bounds rect (include border)
        '''
        w, h = self.contentScale
        return core.Rect(0, 0, w, h)

    def contentBounds(self):
        '''
        :return: projected local bounds rect for contents (without border)
        '''
        rc = self.bounds()
        border = round(self.borderWidth)
        border2 = border * 2
        rc.size = (rc.width - border2, rc.height - border2)
        rc.origin = (rc.x + border, rc.y + border)
        return rc

    def displayBounds(self):
        '''
        :return: unprojected local bounds rect (include border)
        '''
        return self.unprojectLocalRect(self.bounds())

    def contentDisplayBounds(self):
        '''
        :return: unprojected local bounds rect for contents (without border)
        '''
        return self.unprojectLocalRect(self.contentBounds())

    def onRender(self, renderer):
        border = round(self.borderWidth)
        if border > 0:
            renderer.clear(self.borderColor)

            bounds = View.contentBounds(self)
            pixelBounds = self.convertLocalToPixel(
                self.unprojectLocalRect(bounds))

            renderer.viewport = pixelBounds.tuple
            renderer.bounds = bounds.tuple

            _tm = renderer.transform
            renderer.transform = core.Matrix3()

            with renderer.contextForSolidRects(
                    self.backgroundColor, blend=blendstate.defaultOpaque) as r:
                r.add(bounds)

            renderer.transform = _tm

        else:
            renderer.clear(self.backgroundColor)

    def onUpdate(self, delta, tick, date):
        pass

    def onLoaded(self):
        super().onLoaded()
        self.contentScale = tuple(v / self.scaleFactor
                                  for v in self.contentResolution)
        border2 = round(self.borderWidth) * 2
        minWidth = border2 + 1
        minHeight = border2 + 1
        self.minimumViewWidth = max(minWidth, self.minimumViewWidth)
        self.maximumViewHeight = max(minHeight, self.minimumViewHeight)
        if not self.font:
            self.font = font.loadUIFont(self.fontAttributes, self.scaleFactor)
        frame = self.frame
        if frame.width < self.minimumViewWidth:
            frame.height = self.minimumViewWidth
        if frame.height < self.minimumViewHeight:
            frame.height = self.minimumViewHeight
        self.frame = frame

    def onUnload(self):
        self.font = None
        screen = self.screen()
        if screen and screen.frame == self:
            resource.clear()
        super().onUnload()

    def getResolution(self):
        return tuple(v * self.scaleFactor for v in self.__frame.size)

    def contentHitTest(self, pos):
        return self.contentDisplayBounds().isInside(pos)

    def captureMouse(self, deviceId):
        r = super().captureMouse(deviceId)
        screen = self.screen()
        if screen:
            keyboardId = 0
            kf = screen.keyFrame(keyboardId)
            if kf and not kf.isDescendantOf(self):
                self.captureKeyboard(keyboardId)
                self.releaseKeyboard(keyboardId)
        return r
예제 #21
0
파일: checkbox.py 프로젝트: DKGL/DKDemo
class Checkbox(control.Control, view.View):

    boxSize = 14
    boxBorder = 1
    boxBorderColor = core.Color(0, 0, 0)

    leftMargin = 4
    rightMargin = 0
    padding = 8

    boxColor = core.Color(1.0, 1.0, 1.0)
    boxColorHighlighted = core.Color(0.8, 0.8, 1.0)
    boxColorActivated = core.Color(0.3, 0.3, 1.0)
    boxColorDisabled = core.Color(0.6, 0.6, 0.6)

    checkColor = core.Color(0.0, 0.0, 0.0)
    checkColorHighlighted = core.Color(0.0, 0.0, 1.0)
    checkColorActivated = core.Color(0.0, 1.0, 1.0)
    checkColorDisabled = core.Color(0.2, 0.2, 0.2)

    textColor = core.Color(0.0, 0.0, 0.0)
    textColorHighlighted = core.Color(0.0, 0.0, 0.0)
    textColorActivated = core.Color(0.0, 0.0, 0.7)
    textColorDisabled = core.Color(0.3, 0.3, 0.3)

    outlineColor = None
    outlineColorHighlighted = None
    outlineColorActivated = None
    outlineColorDisabled = None

    backgroundColor = core.Color(1, 1, 1)

    fontAttributes = font.attributes(14)

    interactOnlyInsideVisibleContentRect = True

    minimumViewHeight = boxSize + boxBorder * 2
    minimumViewWidth = boxSize + leftMargin + boxBorder * 2

    def __init__(self, text='', value=False, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.text = str(text)
        self.value = value
        self.__mouseHover = False
        self.__activated = False
        self.__capturedMouseId = None
        self.__interactFrame = None

    def onLoaded(self):
        super().onLoaded()

    def onUnload(self):
        super().onUnload()

    def onRender(self, renderer):
        super().onRender(renderer)

        invScale = 1.0 / self.scaleFactor

        state = self.STATE_DISABLED if not self.enabled else \
                self.STATE_ACTIVATED if self.__activated else \
                self.STATE_HIGHLIGHTED if self.__mouseHover else \
                self.STATE_NORMAL

        bounds = self.contentBounds()

        # draw box
        boxRect = core.Rect(bounds.x + self.leftMargin,
                            bounds.y + (bounds.height - self.boxSize) * 0.5,
                            self.boxSize, self.boxSize)

        if self.boxBorder > 0:
            border2 = self.boxBorder * 2
            boxRect.x += self.boxBorder
            rc = core.Rect(boxRect.x - self.boxBorder,
                           boxRect.y - self.boxBorder, boxRect.width + border2,
                           boxRect.height + border2)
            with renderer.contextForSolidRects(
                    self.boxBorderColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

        boxColor = (self.boxColor, self.boxColorHighlighted,
                    self.boxColorActivated, self.boxColorDisabled)[state]

        with renderer.contextForSolidRects(
                boxColor, blend=blendstate.defaultOpaque) as r:
            r.add(boxRect)

        # draw check-mark
        if self.value:
            p0 = core.Point(0.15, 0.6)
            p1 = core.Point(0.05, 0.5)
            p2 = core.Point(0.4, 0.35)
            p3 = core.Point(0.4, 0.15)
            p4 = core.Point(0.85, 0.8)
            p5 = core.Point(0.95, 0.7)
            for p in (p0, p1, p2, p3, p4, p5):
                p.x = p.x * boxRect.width + boxRect.x
                p.y = p.y * boxRect.height + boxRect.y

            checkColor = (self.checkColor, self.checkColorHighlighted,
                          self.checkColorActivated,
                          self.checkColorDisabled)[state]

            with renderer.contextForSolidTriangleStrip(
                    checkColor, blend=blendstate.defaultOpaque) as r:
                r.addTriangle(p0, p1, p2)
                r.add(p3)
                r.add(p4)
                r.add(p5)

        # draw text
        textRect = core.Rect(
            boxRect.x + boxRect.width + self.boxBorder + self.padding,
            bounds.y, 0, bounds.height)
        lineWidth = self.font.lineWidth(self.text) * invScale
        lineHeight = self.font.lineHeight() * invScale
        textRect.width = min(
            bounds.x + bounds.width - textRect.x - self.rightMargin, lineWidth)

        # with renderer.contextForSolidRects(core.Color(1,0,0), blend=blendstate.defaultOpaque) as r:
        #     r.add(textRect)

        textColor = (self.textColor, self.textColorHighlighted,
                     self.textColorActivated, self.textColorDisabled)[state]
        outlineColor = (self.outlineColor, self.outlineColorHighlighted,
                        self.outlineColorActivated,
                        self.outlineColorDisabled)[state]

        font.drawText(renderer,
                      textRect,
                      self.text,
                      self.font,
                      textColor,
                      outlineColor,
                      align=font.ALIGN_LEFT,
                      linebreak=font.LINE_BREAK_TRUNCATING_TAIL,
                      blend=blendstate.defaultAlpha)

        if self.interactOnlyInsideVisibleContentRect:
            x1 = boxRect.x - self.boxBorder - self.padding
            x2 = textRect.x + textRect.width + self.padding

            textOriginY = bounds.y + (bounds.height - lineHeight) * 0.5
            y1 = min(boxRect.y - self.boxBorder, textOriginY) - self.padding
            y2 = max(boxRect.y + boxRect.height,
                     textOriginY + lineHeight) + self.padding

            self.__interactFrame = core.Rect(x1, y1, x2 - x1, y2 - y1)
        else:
            self.__interactFrame = bounds

    def onMouseDown(self, deviceId, buttonId, pos):
        super().onMouseDown(deviceId, buttonId, pos)
        if self.__capturedMouseId:
            if not self.isMouseCapturedBySelf(self.__capturedMouseId[0]):
                self.__capturedMouseId = None

        if self.__capturedMouseId is None:
            if self.__interactFrame and self.__interactFrame.isInside(pos):
                self.captureMouse(deviceId)
                self.__capturedMouseId = (deviceId, buttonId)
                self.__activated = True
                self.redraw()

    def onMouseUp(self, deviceId, buttonId, pos):
        super().onMouseUp(deviceId, buttonId, pos)
        if self.__capturedMouseId and self.__capturedMouseId == (deviceId,
                                                                 buttonId):
            self.releaseMouse(deviceId)
            if self.__interactFrame and self.__interactFrame.isInside(pos):
                self.value = not self.value
                self.screen().postOperation(self.postEvent, ())

            self.__capturedMouseId = None
            self.__activated = False
            self.redraw()

    def onMouseMove(self, deviceId, pos, delta):
        super().onMouseMove(deviceId, pos, delta)
        if self.__capturedMouseId and self.__capturedMouseId[0] == deviceId:
            act = self.__activated
            if self.isMouseCapturedBySelf(deviceId):
                if self.__interactFrame:
                    self.__activated = self.__interactFrame.isInside(pos)
                else:
                    self.__activated = False
            else:
                self.__capturedMouseId = None
                self.__activated = False

            if act != self.__activated:
                self.redraw()

        elif deviceId == 0:
            h = self.__mouseHover
            self.__mouseHover = self.__interactFrame.isInside(
                pos) if self.__interactFrame else False
            if self.__mouseHover != h:
                self.redraw()

    def onMouseLeave(self, deviceId):
        super().onMouseLeave(deviceId)
        if deviceId == 0 and self.__mouseHover:
            self.__mouseHover = False
            self.redraw()

    def postEvent(self):
        super().invokeAllTargets(self)
예제 #22
0
 def randomRectSource(self):
     return core.Size(random.randrange(16, 256),
                      random.randrange(16, 256)), core.Color(
                          random.random(), random.random(), random.random())
예제 #23
0
class TitledView(view.View):

    caption = ''
    captionLeftMargin = 2
    captionRightMargin = 2
    captionTopMargin = 4
    captionBottomMargin = 1
    captionHeight = 28

    contentBorder = 1
    contentMargin = 4
    borderWidth = 1

    movable = True
    pixelBasedMove = True
    clampToParentEdge = True

    fontAttributes = font.attributes(16)

    titleTextColor = core.Color(0, 0, 0)
    titleTextColorHighlighted = core.Color(0, 0, 0)
    titleTextColorActivated = core.Color(1.0, 1.0, 1.0)
    titleTextColorDisabled = core.Color(0.3, 0.3, 0.3)

    titleOutlineColor = None
    titleOutlineColorHighlighted = core.Color(1.0, 1.0, 1.0, 0.75)
    titleOutlineColorActivated = core.Color(0.2, 0.2, 0.2, 0.84)
    titleOutlineColorDisabled = None

    outerBoundColor = core.Color(0.9, 0.9, 0.9)
    outerBoundColorHighlighted = core.Color(0.8, 0.8, 1.0)
    outerBoundColorActivated = core.Color(0.6, 0.6, 1.0)
    outerBoundColorDisabled = core.Color(0.8, 0.8, 0.8)

    minimumViewWidth = borderWidth * 2 + contentBorder * 2 + contentMargin * 2 + 1
    minimumViewHeight = borderWidth * 2 + contentBorder * 2 + contentMargin * 2 + captionHeight + 1

    def __init__(self, caption=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if caption is not None:
            self.caption = str(caption)
        self.__mouseTrackInfo = None
        self.__mouseHover = False

    def orderFront(self):
        parent = self.parent()
        if parent:
            parent.bringChildToFront(self)

    def titleFrame(self):
        border = round(self.contentBorder)
        margin = round(self.contentMargin)
        bounds = super().contentBounds()

        y2 = bounds.y + bounds.height
        y1 = bounds.y + bounds.height - self.captionHeight
        bounds.y = y1
        bounds.height = y2 - y1
        return bounds

    def contentBounds(self):
        border = round(self.contentBorder)
        margin = round(self.contentMargin)
        bounds = super().contentBounds()

        y1 = bounds.y + margin + border
        y2 = bounds.y + bounds.height - self.captionHeight - margin - border
        x1 = bounds.x + margin + border
        x2 = bounds.x + bounds.width - margin - border

        return core.Rect(x1, y1, x2 - x1, y2 - y1)

    def onLoaded(self):
        super().onLoaded()
        b2 = round(self.borderWidth) * 2
        cb2 = round(self.contentBorder) * 2
        m2 = round(self.contentMargin) * 2

        self.minimumViewWidth = b2 + cb2 + m2 + 1
        self.minimumViewHeight = b2 + cb2 + m2 + self.captionHeight + 1

        self.surfaceVisibilityTest = False

    def onUnload(self):
        super().onUnload()

    def __frameClippedByParentBounds(self, frame):
        parent = self.parent()
        if parent:
            try:
                bounds = parent.contentBounds()
            except AttributeError:
                bounds = parent.bounds()

            # make a copy of frame
            frame = core.Rect(frame)
            if frame.width > bounds.width:
                frame.x = bounds.x
            elif frame.x + frame.width > bounds.x + bounds.width:
                frame.x = bounds.x + bounds.width - frame.width
            elif frame.x < bounds.x:
                frame.x = bounds.x
            if frame.height > bounds.height:
                frame.y = bounds.y + bounds.height - frame.height
            elif frame.y + frame.height > bounds.y + bounds.height:
                frame.y = bounds.y + bounds.height - frame.height
            elif frame.y < bounds.y:
                frame.y = bounds.y
        return frame

    def moveToParentInside(self):
        frame = self.__frameClippedByParentBounds(self.frame)
        if frame != self.frame:
            self.frame = frame

    def onUpdate(self, delta, tick, date):
        super().onUpdate(delta, tick, date)
        if self.clampToParentEdge:
            frame = self.__frameClippedByParentBounds(self.frame)
            if frame != self.frame:
                self.frame = frame

    def onRender(self, renderer):
        c = self.backgroundColor
        if self.enabled:
            if self.__mouseTrackInfo:
                self.backgroundColor = self.outerBoundColorActivated
                textColor = self.titleTextColorActivated
                outlineColor = self.titleOutlineColorActivated
            elif self.__mouseHover:
                self.backgroundColor = self.outerBoundColorHighlighted
                textColor = self.titleTextColorHighlighted
                outlineColor = self.titleOutlineColorHighlighted
            else:
                self.backgroundColor = self.outerBoundColor
                textColor = self.titleTextColor
                outlineColor = self.titleOutlineColor
        else:
            self.backgroundColor = self.outerBoundColorDisabled
            textColor = self.titleTextColorDisabled
            outlineColor = self.titleOutlineColorDisabled

        super().onRender(renderer)
        self.backgroundColor = c

        _tm = renderer.transform
        renderer.transform = core.Matrix3()

        titleRect = self.titleFrame()
        titleRect.x += self.captionLeftMargin
        titleRect.width -= self.captionLeftMargin + self.captionRightMargin
        titleRect.y += self.captionBottomMargin
        titleRect.height -= self.captionTopMargin + self.captionBottomMargin
        font.drawText(renderer,
                      titleRect,
                      self.caption,
                      self.font,
                      textColor,
                      outlineColor,
                      align=font.ALIGN_BOTTOM)

        bounds = TitledView.contentBounds(self)
        border = round(self.contentBorder)
        if border > 0:
            rc = core.Rect(bounds)
            rc.x -= border
            rc.width += border * 2
            rc.y -= border
            rc.height += border * 2
            with renderer.contextForSolidRects(
                    self.borderColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)
        with renderer.contextForSolidRects(
                self.backgroundColor, blend=blendstate.defaultOpaque) as r:
            r.add(bounds)

        pixelBounds = self.convertLocalToPixel(self.unprojectLocalRect(bounds))
        renderer.viewport = pixelBounds.tuple
        renderer.bounds = bounds.tuple
        renderer.transform = _tm

    def onMouseDown(self, deviceId, buttonId, pos):
        super().onMouseDown(deviceId, buttonId, pos)
        if buttonId == 0 and not self.__mouseTrackInfo:
            self.screen().postOperation(self.orderFront, ())
            bounds = self.bounds()
            contentBounds = TitledView.contentBounds(self)
            pos = self.projectLocalPoint(pos)
            if bounds.isInside(pos) and not contentBounds.isInside(pos):
                self.__mouseTrackInfo = _MouseTrackInfo(deviceId, pos)
                self.captureMouse(deviceId)
                self.redraw()

    def onMouseUp(self, deviceId, buttonId, pos):
        super().onMouseUp(deviceId, buttonId, pos)
        if buttonId == 0 and self.__mouseTrackInfo and self.__mouseTrackInfo.deviceId == deviceId:
            self.__mouseTrackInfo = None
            self.releaseMouse(deviceId)
            self.redraw()
            if deviceId == 0 and not self.__mouseHover:
                bounds = self.bounds()
                contentBounds = self.contentBounds()
                pos = self.projectLocalPoint(pos)
                if bounds.isInside(pos) and not contentBounds.isInside(pos):
                    self.__mouseHover = True

    def onMouseMove(self, deviceId, pos, delta):
        super().onMouseMove(deviceId, pos, delta)
        if self.__mouseTrackInfo and self.__mouseTrackInfo.deviceId == deviceId:
            if self.isMouseCapturedBySelf(deviceId):
                if self.movable:
                    parent = self.parent()
                    if parent:
                        bounds = parent.contentDisplayBounds()
                        v1 = self.unprojectLocalPoint(
                            self.__mouseTrackInfo.pos).vector()
                        v2 = pos.vector()
                        tm = self.localToParentTransformMatrix()
                        v1.transform(tm)
                        v2.transform(tm)

                        x1, x2 = bounds.x, bounds.x + bounds.width
                        y1, y2 = bounds.y, bounds.y + bounds.height

                        v2.x = x1 if v2.x < x1 else x2 if v2.x > x2 else v2.x
                        v2.y = y1 if v2.y < y1 else y2 if v2.y > y2 else v2.y

                        offset = v2 - v1
                        frame = self.frame
                        frame.origin = frame.x + offset.x, frame.y + offset.y

                        if self.clampToParentEdge:
                            frame = self.__frameClippedByParentBounds(frame)

                        if self.pixelBasedMove:
                            p = parent.convertLocalToPixel(
                                core.Point(frame.origin))
                            p.tuple = round(p.x), round(p.y)
                            frame.origin = parent.convertPixelToLocal(p)

                        if frame != self.frame:
                            self.screen().postOperation(
                                self.setFrame, (frame, ))

            else:  # we lost mouse
                self.__mouseTrackInfo = None
                self.redraw()

        elif deviceId == 0:  # process hover
            if not self.__mouseHover:
                self.__mouseHover = True
                if not self.__mouseTrackInfo:
                    self.redraw()

    def onMouseLeave(self, deviceId):
        super().onMouseLeave(deviceId)
        if deviceId == 0 and self.__mouseHover:
            self.__mouseHover = False
            if not self.__mouseTrackInfo:
                self.redraw()

    def frameForContentFrame(self, frame):
        frameBorder = round(self.borderWidth)
        contentBorder = round(self.contentBorder)
        margin = round(self.contentMargin)

        x1 = frame.x - (margin + contentBorder + frameBorder)
        x2 = frame.x + frame.width + (margin + contentBorder + frameBorder)
        y1 = frame.y - (margin + contentBorder + frameBorder)
        y2 = frame.y + frame.height + (margin + contentBorder + frameBorder +
                                       self.captionHeight)

        return core.Rect(x1, y1, x2 - x1, y2 - y1)
예제 #24
0
파일: scrollview.py 프로젝트: DKGL/DKDemo
class ScrollView(view.View):

    scrollBarBorderWidth = 1
    scrollBarSize = 16
    scrollSliderMinimumLength = 10

    showVerticalScrollBar = False
    showHorizontalScrollBar = False
    showZoomButton = False
    leftScrollBar = False

    minimumZoomScale = 0.1
    maximumZoomScale = 10

    _activatedColor = core.Color(0.6, 0.6, 1.0)
    _highlightedColor = core.Color(0.8, 0.8, 1.0)
    _disabledColor = core.Color(0.4, 0.4, 0.4)

    scrollTrackColor = core.Color(0.5, 0.5, 0.5)
    scrollTrackColorHighlighted = core.Color(0.65, 0.65, 0.65)
    scrollTrackColorDisabled = _disabledColor

    scrollSliderColor = core.Color(0.87, 0.87, 0.87)
    scrollSliderColorHighlighted = _highlightedColor
    scrollSliderColorActivated = _activatedColor

    zoomButtonColor = core.Color(0.87, 0.87, 0.87)
    zoomButtonColorHighlighted = _highlightedColor
    zoomButtonColorActivated = _activatedColor
    zoomButtonColorDisabled = _disabledColor

    def __init__(self, contentSize=None, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.__zoomScale = 1.0
        self.__contentOffset = core.Point(0, 0)
        if contentSize:
            assert isinstance(contentSize, core.Size)
            scaleX, scaleY = self.contentScale
            width = max(contentSize.width, scaleX)
            height = max(contentSize.height, scaleY)
            self.__contentSize = core.Size(width, height)
        else:
            self.__contentSize = core.Size(0, 0)

        self.__verticalScrollTrackRect = None
        self.__verticalScrollSliderRect = None
        self.__horizontalScrollTrackRect = None
        self.__horizontalScrollSliderRect = None
        self.__zoomButtonRect = None

        self.__mouseHoverPos = 0
        self.__mouseTrackInfo = None
        self.__updateContentTransform = False

    @property
    def contentOffset(self):
        return self.__contentOffset

    @contentOffset.setter
    def contentOffset(self, value):
        self.__contentOffset = value
        self.__updateContentTransform = True

    @property
    def contentSize(self):
        return self.__contentSize

    @contentSize.setter
    def contentSize(self, value):
        self.__contentSize = value
        self.__updateContentTransform = True

    @property
    def zoomScale(self):
        return self.__zoomScale

    @zoomScale.setter
    def zoomScale(self, value):
        self.__zoomScale = value
        self.__updateContentTransform = True

    def layout(self):
        if self.layouter:
            self.layouter(self.contentBounds(), self.children())

    def onLoaded(self):
        super().onLoaded()
        self._updateScrollTrackRect()
        self.updateContentTransform()

    def contentBounds(self):
        """
        calculate actual display bounds.
        bounds NOT INCLUDES scroll-bar area!!
        """
        border = round(self.scrollBarBorderWidth)
        bounds = super().contentBounds()

        if bounds.width < border + self.scrollBarSize:
            self.showVerticalScrollBar = False
        if bounds.height < border + self.scrollBarSize:
            self.showHorizontalScrollBar = False

        if self.showVerticalScrollBar:
            bounds.width -= self.scrollBarSize + border
            if self.leftScrollBar:
                bounds.x += self.scrollBarSize + border
        if self.showHorizontalScrollBar:
            bounds.height -= self.scrollBarSize + border
            bounds.y += self.scrollBarSize + border
        return bounds

    def contentDisplayBounds(self):
        """
        calculate content-bounds NOT INCLUDES scroll-bar area.
        result bounds is not same as visible area. (applied with scale, includes scrollable area)
        """
        border = round(self.scrollBarBorderWidth)
        bounds = super().contentBounds()
        bounds = super().unprojectLocalRect(bounds)

        if bounds.width < border + self.scrollBarSize:
            self.showVerticalScrollBar = False
        if bounds.height < border + self.scrollBarSize:
            self.showHorizontalScrollBar = False

        if self.showVerticalScrollBar:
            bounds.width -= self.scrollBarSize + border
            if self.leftScrollBar:
                bounds.x += self.scrollBarSize + border
        if self.showHorizontalScrollBar:
            bounds.height -= self.scrollBarSize + border
            bounds.y += self.scrollBarSize + border
        return bounds

    def maxScrollOffset(self):
        bounds = self.contentBounds()
        scaleX = bounds.width / self.__zoomScale
        scaleY = bounds.height / self.__zoomScale

        maxX = max(self.__contentSize.width - scaleX, 0)
        maxY = max(self.__contentSize.height - scaleY, 0)

        return maxX, maxY

    def _updateScrollSliderRect(self):

        self.__verticalScrollSliderRect = None
        self.__horizontalScrollSliderRect = None

        if self.showVerticalScrollBar or self.showHorizontalScrollBar:
            # print('_updateScrollSliderRect ({})'.format(core.Timer.tick()))

            bounds = self.contentBounds()

            if self.showVerticalScrollBar:
                scale = bounds.height / self.__zoomScale
                scrollMax = self.__contentSize.height - scale
                if scrollMax > 0 and self.__verticalScrollTrackRect.height > 2:
                    rc = core.Rect(self.__verticalScrollTrackRect)
                    pos = self.__contentOffset.y / scrollMax
                    height = rc.height

                    sliderMinLength = self.scrollSliderMinimumLength
                    if sliderMinLength >= rc.height:
                        sliderMinLength = rc.height * 0.5

                    rc.height = (
                        rc.height - sliderMinLength
                    ) * scale / self.__contentSize.height + sliderMinLength
                    rc.y += (height - rc.height) * pos
                    self.__verticalScrollSliderRect = rc

            if self.showHorizontalScrollBar:
                scale = bounds.width / self.__zoomScale
                scrollMax = self.__contentSize.width - scale
                if scrollMax > 0 and self.__horizontalScrollTrackRect.height > 2:
                    rc = core.Rect(self.__horizontalScrollTrackRect)
                    pos = self.__contentOffset.x / scrollMax
                    width = rc.width

                    sliderMinLength = self.scrollSliderMinimumLength
                    if sliderMinLength >= rc.width:
                        sliderMinLength = rc.width * 0.5

                    rc.width = (
                        rc.width - sliderMinLength
                    ) * scale / self.__contentSize.width + sliderMinLength
                    rc.x += (width - rc.width) * pos
                    self.__horizontalScrollSliderRect = rc

    def _updateScrollTrackRect(self):
        self.__verticalScrollTrackRect = None
        self.__horizontalScrollTrackRect = None
        self.__zoomButtonRect = None

        if self.showVerticalScrollBar or self.showHorizontalScrollBar:
            # print('_updateScrollTrackRect')

            border = round(self.scrollBarBorderWidth)
            bounds = self.contentBounds()
            scrollBarSize = self.scrollBarSize

            if self.showVerticalScrollBar:
                rc = core.Rect()
                rc.width = scrollBarSize
                if self.leftScrollBar:
                    rc.x = bounds.x - scrollBarSize - border
                else:
                    rc.x = bounds.x + bounds.width + border
                if not self.showHorizontalScrollBar and self.showZoomButton:
                    rc.y = bounds.y + scrollBarSize + border
                    rc.height = bounds.height - scrollBarSize
                else:
                    rc.y = bounds.y
                    rc.height = bounds.height
                self.__verticalScrollTrackRect = rc

            if self.showHorizontalScrollBar:
                rc = core.Rect()
                rc.x = bounds.x
                rc.y = bounds.y - scrollBarSize - border
                rc.height = scrollBarSize
                if not self.showVerticalScrollBar and self.showZoomButton:
                    rc.width = bounds.width - scrollBarSize + border
                    if self.leftScrollBar:
                        rc.x = bounds.x + scrollBarSize + border
                else:
                    rc.width = bounds.width
                self.__horizontalScrollTrackRect = rc

            zoomRectShouldVisible = self.showVerticalScrollBar and self.showHorizontalScrollBar
            if zoomRectShouldVisible or self.showZoomButton:
                rc = core.Rect()
                rc.width = scrollBarSize
                rc.height = scrollBarSize
                if self.showVerticalScrollBar:
                    if self.leftScrollBar:
                        rc.x = bounds.x - scrollBarSize - border
                    else:
                        rc.x = bounds.x + bounds.width + border
                else:
                    if self.leftScrollBar:
                        rc.x = bounds.x
                    else:
                        rc.x = bounds.x + bounds.width - scrollBarSize
                if self.showHorizontalScrollBar:
                    rc.y = bounds.y - scrollBarSize - border
                else:
                    rc.y = bounds.y
                self.__zoomButtonRect = rc

            self._updateScrollSliderRect()

    def onResized(self):
        super().onResized()
        self.updateContentTransform()
        if self.surfaceVisibilityTest:
            if self.showHorizontalScrollBar or self.showVerticalScrollBar:
                self.surfaceVisibilityTest = False

        self._updateScrollTrackRect()

    def onUpdate(self, delta, tick, date):
        super().onUpdate(delta, tick, date)
        if self.__updateContentTransform:
            self.updateContentTransform()

    def onRender(self, renderer):
        super().onRender(renderer)

        border = round(self.scrollBarBorderWidth) / self.__zoomScale
        border2 = border * 2

        trackPos = self.__mouseTrackInfo.type if self.__mouseTrackInfo else 0
        hoverPos = self.__mouseHoverPos

        if self.__verticalScrollTrackRect:
            rc = self.unprojectLocalRect(self.__verticalScrollTrackRect)

            if border > 0:
                with renderer.contextForSolidRects(
                        self.borderColor, blend=blendstate.defaultOpaque) as r:
                    r.add(
                        core.Rect(rc.x - border, rc.y - border,
                                  rc.width + border2, rc.height + border2))

            color = self.scrollTrackColorHighlighted if hoverPos == _POS_VERTICAL_SCROLL_TRACK \
                else self.scrollTrackColor if self.__verticalScrollSliderRect \
                else self.scrollTrackColorDisabled

            with renderer.contextForSolidRects(
                    color, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

            if self.__verticalScrollSliderRect:
                rc = self.unprojectLocalRect(self.__verticalScrollSliderRect)

                color = self.scrollSliderColorActivated if trackPos == _POS_VERTICAL_SCROLL_SLIDER \
                    else self.scrollSliderColorHighlighted if hoverPos == _POS_VERTICAL_SCROLL_SLIDER \
                    else self.scrollSliderColor

                with renderer.contextForSolidRects(
                        color, blend=blendstate.defaultOpaque) as r:
                    r.add(rc)

        if self.__horizontalScrollTrackRect:
            rc = self.unprojectLocalRect(self.__horizontalScrollTrackRect)
            if border > 0:
                with renderer.contextForSolidRects(
                        self.borderColor, blend=blendstate.defaultOpaque) as r:
                    r.add(
                        core.Rect(rc.x - border, rc.y - border,
                                  rc.width + border2, rc.height + border2))

            color = self.scrollTrackColorHighlighted if hoverPos == _POS_HORIZONTAL_SCROLL_TRACK \
                else self.scrollTrackColor if self.__horizontalScrollSliderRect \
                else self.scrollTrackColorDisabled

            with renderer.contextForSolidRects(
                    color, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

            if self.__horizontalScrollSliderRect:
                rc = self.unprojectLocalRect(self.__horizontalScrollSliderRect)

                color = self.scrollSliderColorActivated if trackPos == _POS_HORIZONTAL_SCROLL_SLIDER \
                    else self.scrollSliderColorHighlighted if hoverPos == _POS_HORIZONTAL_SCROLL_SLIDER \
                    else self.scrollSliderColor

                with renderer.contextForSolidRects(
                        color, blend=blendstate.defaultOpaque) as r:
                    r.add(rc)

        if self.__zoomButtonRect:
            rc = self.unprojectLocalRect(self.__zoomButtonRect)
            if border > 0:
                with renderer.contextForSolidRects(
                        self.borderColor, blend=blendstate.defaultOpaque) as r:
                    r.add(
                        core.Rect(rc.x - border, rc.y - border,
                                  rc.width + border2, rc.height + border2))

            activated = trackPos == _POS_ZOOM_BUTTON
            if activated:
                pos = self.__mouseTrackInfo.offset + self.__zoomButtonRect.origin
                activated = self.__zoomButtonRect.isInside(pos)

            color = self.zoomButtonColorDisabled if not self.showZoomButton \
                else self.zoomButtonColorActivated if activated \
                else self.zoomButtonColorHighlighted if hoverPos == _POS_ZOOM_BUTTON \
                else self.zoomButtonColor

            with renderer.contextForSolidRects(
                    color, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

        x, y = self.contentScale
        w, h = self.contentResolution
        scaleX = w / x
        scaleY = h / y

        bounds = self.contentBounds()
        renderer.viewport = bounds.x * scaleX, bounds.y * scaleY, bounds.width * scaleX, bounds.height * scaleY
        renderer.bounds = bounds

    def updateContentTransform(self):
        clamp = lambda x, minV, maxV: minV if x < minV else maxV if x > maxV else x

        if self.minimumZoomScale < 0.1:
            self.minimumZoomScale = 0.1
        if self.maximumZoomScale < self.minimumZoomScale:
            self.maximumZoomScale = self.minimumZoomScale

        self.__zoomScale = clamp(self.__zoomScale, self.minimumZoomScale,
                                 self.maximumZoomScale)

        bounds = self.contentBounds()
        scaleX = bounds.width / self.__zoomScale
        scaleY = bounds.height / self.__zoomScale

        maxX = max(self.__contentSize.width - scaleX, 0)
        maxY = max(self.__contentSize.height - scaleY, 0)

        self.__contentOffset.x = clamp(self.__contentOffset.x, 0, maxX)
        self.__contentOffset.y = clamp(self.__contentOffset.y, 0, maxY)

        scale = core.LinearTransform2()
        scale.scale(self.__zoomScale)
        transform = core.AffineTransform2()
        transform.translate(-self.__contentOffset.x, -self.__contentOffset.y)
        transform.multiply(scale)
        transform.translate(bounds.x, bounds.y)
        tm = transform.matrix3()
        if self.contentTransform != tm:
            self.contentTransform = tm
            self._updateScrollSliderRect()
            self.redraw()
        self.__updateContentTransform = False

    def onClickZoomButton(self):
        print('user click zoom-button')
        if self.__zoomScale != 1.0:
            self.__zoomScale = 1.0
        else:
            self.__zoomScale = self.minimumZoomScale
        self.updateContentTransform()

    def setContentOffset(self, x, y):
        if self.__contentOffset.x != x or self.__contentOffset.y != y:
            self.__contentOffset.tuple = x, y
            self.updateContentTransform()

    def onMouseDown(self, deviceId, buttonId, pos):
        super().onMouseDown(deviceId, buttonId, pos)
        if not self.__mouseTrackInfo and not self.isMouseCapturedBySelf(
                deviceId):
            bounds = self.contentBounds()
            pos = self.projectLocalPoint(pos)
            if not bounds.isInside(pos):
                mouseId = (deviceId, buttonId)
                if self.__verticalScrollSliderRect:
                    if self.__verticalScrollSliderRect.isInside(pos):
                        self.captureMouse(deviceId)
                        offset = pos - self.__verticalScrollSliderRect.origin
                        self.__mouseTrackInfo = _MouseTrackPos(
                            mouseId, _POS_VERTICAL_SCROLL_SLIDER, offset)
                        if self.__mouseHoverPos in (
                                _POS_VERTICAL_SCROLL_SLIDER,
                                _POS_VERTICAL_SCROLL_TRACK):
                            self.__mouseHoverPos = 0  # release mouse hover!
                        self.redraw()
                        return
                    if self.__verticalScrollTrackRect.isInside(pos):
                        range = self.__verticalScrollTrackRect.height - self.__verticalScrollSliderRect.height
                        if range > 0:
                            offset = pos.y - self.__verticalScrollTrackRect.y - self.__verticalScrollSliderRect.height * 0.5
                            maxValue = max(
                                self.__contentSize.height -
                                bounds.height / self.__zoomScale, 0)
                            offset = 0.0 if offset < 0.0 else maxValue if offset > range else offset * maxValue / range
                            self.screen().postOperation(
                                self.setContentOffset,
                                (self.__contentOffset.x, offset))
                        return

                if self.__horizontalScrollSliderRect:
                    if self.__horizontalScrollSliderRect.isInside(pos):
                        self.captureMouse(deviceId)
                        offset = pos - self.__horizontalScrollSliderRect.origin
                        self.__mouseTrackInfo = _MouseTrackPos(
                            mouseId, _POS_HORIZONTAL_SCROLL_SLIDER, offset)
                        if self.__mouseHoverPos in (
                                _POS_HORIZONTAL_SCROLL_SLIDER,
                                _POS_HORIZONTAL_SCROLL_TRACK):
                            self.__mouseHoverPos = 0  # release mouse hover
                        self.redraw()
                        return
                    if self.__horizontalScrollTrackRect.isInside(pos):
                        range = self.__horizontalScrollTrackRect.width - self.__horizontalScrollSliderRect.width
                        if range > 0:
                            offset = pos.x - self.__horizontalScrollTrackRect.x - self.__horizontalScrollSliderRect.width * 0.5
                            maxValue = max(
                                self.__contentSize.width -
                                bounds.width / self.__zoomScale, 0)
                            offset = 0.0 if offset < 0.0 else maxValue if offset > range else offset * maxValue / range
                            self.screen().postOperation(
                                self.setContentOffset,
                                (offset, self.__contentOffset.y))
                        return

                if self.showZoomButton and self.__zoomButtonRect:
                    if self.__zoomButtonRect.isInside(pos):
                        self.captureMouse(deviceId)
                        offset = pos - self.__zoomButtonRect.origin
                        self.__mouseTrackInfo = _MouseTrackPos(
                            mouseId, _POS_ZOOM_BUTTON, offset)
                        if self.__mouseHoverPos == _POS_ZOOM_BUTTON:
                            self.__mouseHoverPos = 0
                        self.redraw()
                        return

    def onMouseMove(self, deviceId, pos, delta):
        super().onMouseMove(deviceId, pos, delta)
        if self.__mouseTrackInfo and self.__mouseTrackInfo.mouseId[
                0] == deviceId:
            if self.isMouseCapturedBySelf(deviceId):
                bounds = self.contentBounds()
                pos = self.projectLocalPoint(pos)
                if self.__mouseTrackInfo.type == _POS_ZOOM_BUTTON:
                    pos_old = core.Point(self.__mouseTrackInfo.offset +
                                         self.__zoomButtonRect.origin)
                    act1 = self.__zoomButtonRect.isInside(pos_old)
                    act2 = self.__zoomButtonRect.isInside(pos)
                    self.__mouseTrackInfo.offset.tuple = (
                        pos - self.__zoomButtonRect.origin).tuple
                    if act1 != act2:  # zoom-button activation state changed.
                        self.redraw()
                elif self.__mouseTrackInfo.type == _POS_VERTICAL_SCROLL_SLIDER:
                    if self.__verticalScrollSliderRect:
                        range = self.__verticalScrollTrackRect.height - self.__verticalScrollSliderRect.height
                        if range > 0:
                            offset = pos.y - self.__mouseTrackInfo.offset.y - self.__verticalScrollTrackRect.y
                            maxValue = max(
                                self.__contentSize.height -
                                bounds.height / self.__zoomScale, 0)
                            offset = 0.0 if offset < 0.0 else maxValue if offset > range else offset * maxValue / range
                            self.screen().postOperation(
                                self.setContentOffset,
                                (self.__contentOffset.x, offset))
                elif self.__mouseTrackInfo.type == _POS_HORIZONTAL_SCROLL_SLIDER:
                    if self.__horizontalScrollSliderRect:
                        range = self.__horizontalScrollTrackRect.width - self.__horizontalScrollSliderRect.width
                        if range > 0:
                            offset = pos.x - self.__mouseTrackInfo.offset.x - self.__horizontalScrollTrackRect.x
                            maxValue = max(
                                self.__contentSize.width -
                                bounds.width / self.__zoomScale, 0)
                            offset = 0.0 if offset < 0.0 else maxValue if offset > range else offset * maxValue / range
                            self.screen().postOperation(
                                self.setContentOffset,
                                (offset, self.__contentOffset.y))
            else:
                self.__mouseTrackInfo = None
                self.redraw()
        elif deviceId == 0:
            hoverPos = 0
            if not self.isMouseCapturedBySelf(deviceId):
                bounds = self.contentBounds()
                pos = self.projectLocalPoint(pos)
                if not bounds.isInside(pos):
                    trackPos = self.__mouseTrackInfo.type if self.__mouseTrackInfo else 0
                    if hoverPos == 0 and trackPos not in (
                            _POS_VERTICAL_SCROLL_SLIDER,
                            _POS_VERTICAL_SCROLL_TRACK):
                        # check mouse hover on vertical scroll
                        if self.__verticalScrollSliderRect:
                            if self.__verticalScrollSliderRect.isInside(pos):
                                hoverPos = _POS_VERTICAL_SCROLL_SLIDER
                            elif self.__verticalScrollTrackRect.isInside(pos):
                                hoverPos = _POS_VERTICAL_SCROLL_TRACK
                    if hoverPos == 0 and trackPos not in (
                            _POS_HORIZONTAL_SCROLL_SLIDER,
                            _POS_HORIZONTAL_SCROLL_TRACK):
                        # check mouse hover on horizontal scroll
                        if self.__horizontalScrollSliderRect:
                            if self.__horizontalScrollSliderRect.isInside(pos):
                                hoverPos = _POS_HORIZONTAL_SCROLL_SLIDER
                            elif self.__horizontalScrollTrackRect.isInside(
                                    pos):
                                hoverPos = _POS_HORIZONTAL_SCROLL_TRACK
                    if hoverPos == 0 and trackPos != _POS_ZOOM_BUTTON:
                        if self.showZoomButton and self.__zoomButtonRect:
                            if self.__zoomButtonRect.isInside(pos):
                                hoverPos = _POS_ZOOM_BUTTON

            if self.__mouseHoverPos != hoverPos:
                self.__mouseHoverPos = hoverPos
                self.redraw()

    def onMouseUp(self, deviceId, buttonId, pos):
        super().onMouseUp(deviceId, buttonId, pos)
        if self.__mouseTrackInfo and self.__mouseTrackInfo.mouseId == (
                deviceId, buttonId):
            bounds = self.contentBounds()
            pos = self.projectLocalPoint(pos)

            if self.__mouseTrackInfo.type == _POS_ZOOM_BUTTON:
                if self.__zoomButtonRect and self.__zoomButtonRect.isInside(
                        pos):
                    self.screen().postOperation(self.onClickZoomButton, ())

            if deviceId == 0 and self.__mouseHoverPos == 0:
                self.__mouseHoverPos = self.__mouseTrackInfo.type

            self.releaseMouse(deviceId)
            self.__mouseTrackInfo = None
            self.redraw()

    def onMouseLeave(self, deviceId):
        super().onMouseLeave(deviceId)
        if deviceId == 0 and self.__mouseHoverPos:
            self.__mouseHoverPos = 0
            if not self.__mouseTrackInfo:
                self.redraw()

    def onMouseWheel(self, deviceId, pos, delta):
        super().onMouseWheel(deviceId, pos, delta)
        window = self.screen().window
        from .. import vkey
        if window.isKeyDown(0, vkey.LEFT_OPTION):
            offset = 0.05 if delta.y > 0.0 else -0.05
            zoomScale = self.__zoomScale + offset
            self.__zoomScale = max(zoomScale, 0.1)
        else:
            # OS X does handles vertical scroll while holding down shift-key.
            # if window.isKeyDown(0, vkey.LEFT_SHIFT):
            #     self.__contentOffset.x -= delta.y * 10
            #     self.__contentOffset.y += delta.x * 10
            # else:
            self.__contentOffset.x -= delta.x * 10
            self.__contentOffset.y += delta.y * 10
        self.updateContentTransform()

    def preprocessMouseEvent(self, type, deviceId, buttonId, pos, delta):
        if type == window.MOUSE_EVENT_MOVE and self.__mouseHoverPos:
            if self.screen().focusFrame(deviceId) is not None:

                bounds = self.contentBounds()
                pos = self.projectLocalPoint(pos)
                if bounds.isInside(pos):
                    self.__mouseHoverPos = 0
                    self.redraw()
            else:
                self.__mouseHoverPos = 0
                self.redraw()

        # 마우스가 자식 위로 올라가면.. 호버 없애야 함.
        return super().preprocessMouseEvent(type, deviceId, buttonId, pos,
                                            delta)
예제 #25
0
파일: progress.py 프로젝트: DKGL/DKDemo
class RoundedBarProgressView(AnimatedProgressView):

    borderWidth = 1
    borderColor = core.Color(0.0, 0.0, 0.0)

    backgroundColor = core.Color(0.5, 0.5, 0.5)
    progressColor = core.Color(1.0, 1.0, 1.0)

    minimumViewHeight = borderWidth * 2 + 1
    minimumViewWidth = borderWidth * 2 + 1

    cornerRadius = 8
    vertical = False

    def __init__(self,
                 initialValue=0.0,
                 minValue=0.0,
                 maxValue=1.0,
                 *args,
                 **kwargs):
        super().__init__(initialValue, minValue, maxValue, *args, **kwargs)
        self.setBlendState(blendstate.defaultAlpha)
        self.__bsLayerMask1 = None
        self.__bsLayerMask2 = None

    def discardSurface(self):
        super().discardSurface()
        self.__bsLayerMask1 = None
        self.__bsLayerMask2 = None

    def onResized(self):
        super().onResized()
        self.__bsLayerMask1 = None
        self.__bsLayerMask2 = None

    def onLoaded(self):
        super().onLoaded()
        self.__bsLayerMask1 = None
        self.__bsLayerMask2 = None

    def onUnload(self):
        super().onUnload()
        self.__bsLayerMask1 = None
        self.__bsLayerMask2 = None

    def onRender(self, renderer):
        border = round(self.borderWidth)
        border2 = border * 2
        radius = round(self.cornerRadius)
        bounds = self.bounds()

        cornerRadius = min(radius,
                           math.floor(bounds.height * 0.5) - border,
                           math.floor(bounds.width * 0.5) - border)

        if cornerRadius > 1:
            texSize = (cornerRadius + border) * 2
            cornerRadius2 = cornerRadius * 2
            if self.__bsLayerMask1 is None:
                rt = rendertarget.RenderTarget(texSize * self.scaleFactor,
                                               texSize * self.scaleFactor,
                                               rendertarget.DEPTH_NONE)
                rd = Renderer(rt)
                rd.bounds = 0, 0, texSize, texSize
                rd.clear(core.Color(0, 0, 0, 0))
                with rd.contextForSolidEllipses(
                        core.Color(1, 1, 1,
                                   1), blend=blendstate.defaultOpaque) as r:
                    r.add(
                        core.Rect(border, border, cornerRadius2,
                                  cornerRadius2))
                self.__bsLayerMask1 = rt.colorTextureAtIndex(0)

            if border > 0:
                if self.__bsLayerMask2 is None:
                    rt = rendertarget.RenderTarget(texSize * self.scaleFactor,
                                                   texSize * self.scaleFactor,
                                                   rendertarget.DEPTH_NONE)
                    rd = Renderer(rt)
                    rd.bounds = 0, 0, texSize, texSize
                    rd.clear(core.Color(0, 0, 0, 0))
                    with rd.contextForSolidEllipses(
                            self.borderColor,
                            blend=blendstate.defaultOpaque) as r:
                        r.add(core.Rect(0, 0, texSize, texSize))
                    with rd.contextForSolidEllipses(
                            core.Color(0, 0, 0, 0),
                            blend=blendstate.defaultOpaque) as r:
                        r.add(
                            core.Rect(border, border, cornerRadius2,
                                      cornerRadius2))
                    self.__bsLayerMask2 = rt.colorTextureAtIndex(0)
            else:
                self.__bsLayerMask2 = None
        else:
            self.__bsLayerMask1 = None
            self.__bsLayerMask2 = None

        rc = core.Rect(bounds.x + border, bounds.y + border,
                       bounds.width - border2, bounds.height - border2)
        prog = self._progress / (self.maximumValue - self.minimumValue)
        if prog < 0.0: prog = 0.0
        if prog > 1.0: prog = 1.0
        if self.vertical:
            rc.height = rc.height * prog
        else:
            rc.width = rc.width * prog

        if border > 0:
            renderer.clear(self.borderColor)
            with renderer.contextForSolidRects(
                    self.progressColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

            if self.vertical:
                rc.y += rc.height
                rc.height = (bounds.height - border2) - rc.height
            else:
                rc.x += rc.width
                rc.width = (bounds.width - border2) - rc.width

            with renderer.contextForSolidRects(
                    self.backgroundColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

        else:
            renderer.clear(self.backgroundColor)
            with renderer.contextForSolidRects(
                    self.progressColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

        if self.__bsLayerMask1:
            invScale = 1.0 / self.scaleFactor
            x = self.__bsLayerMask1.width * 0.5 * invScale
            y = self.__bsLayerMask1.height * 0.5 * invScale
            with renderer.contextForTexturedRects(
                    self.__bsLayerMask1, blend=blendstate.defaultDarken) as r:
                r.add(core.Rect(bounds.x, bounds.y, x, y), _identityMatrix3,
                      core.Rect(0, 0, 0.5, 0.5))
                r.add(core.Rect(bounds.x, bounds.y + bounds.height - y, x, y),
                      _identityMatrix3, core.Rect(0, 0.5, 0.5, 0.5))
                r.add(
                    core.Rect(bounds.x + bounds.width - x,
                              bounds.y + bounds.height - y, x, y),
                    _identityMatrix3, core.Rect(0.5, 0.5, 0.5, 0.5))
                r.add(core.Rect(bounds.x + bounds.width - x, bounds.y, x, y),
                      _identityMatrix3, core.Rect(0.5, 0.0, 0.5, 0.5))

            if self.__bsLayerMask2:
                x = self.__bsLayerMask2.width * 0.5 * invScale
                y = self.__bsLayerMask2.height * 0.5 * invScale
                with renderer.contextForTexturedRects(
                        self.__bsLayerMask2,
                        blend=blendstate.defaultAlpha) as r:
                    r.add(core.Rect(bounds.x, bounds.y, x, y),
                          _identityMatrix3, core.Rect(0, 0, 0.5, 0.5))
                    r.add(
                        core.Rect(bounds.x, bounds.y + bounds.height - y, x,
                                  y), _identityMatrix3,
                        core.Rect(0, 0.5, 0.5, 0.5))
                    r.add(
                        core.Rect(bounds.x + bounds.width - x,
                                  bounds.y + bounds.height - y, x, y),
                        _identityMatrix3, core.Rect(0.5, 0.5, 0.5, 0.5))
                    r.add(
                        core.Rect(bounds.x + bounds.width - x, bounds.y, x, y),
                        _identityMatrix3, core.Rect(0.5, 0.0, 0.5, 0.5))
예제 #26
0
파일: menu.py 프로젝트: DKGL/DKDemo
class Menu(view.View):

    minimumViewHeight = 16
    minimumViewWidth = 16

    fontAttributes = font.attributes(12)

    backgroundColor = core.Color(0.94, 0.94, 0.94)
    backgroundColorHighlighted = core.Color(0.2, 0.2, 1)

    borderColor = core.Color(0, 0, 0)
    borderWidth = 1

    margin = 2  # left,right,bottom,up margin
    itemPadding = 1  # padding between menu items

    verticalLayout = False

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.style = ItemStyle()
        self.__items = []
        self.__highlightedItem = None
        self.__selectedItem = None
        self.__popup = False
        self.__popupChild = None
        self.__capturedMouseId = None
        self.__capturedMouseDown = False
        self.__autoExpand = False

    def items(self):
        return tuple(self.__items)

    def findItem(self, text):
        for item in self.__items:
            try:
                if item.text == text:
                    return item
            except AttributeError:
                pass

    def removeItem(self, item):
        if item.menu != self:
            raise ValueError('Invalid menu item object.')

        self.__items.remove(item)
        item.style = None
        item._menu = None
        self.__highlightedItem = None
        self.redraw()

    def addItem(self, text):
        item = Item(text, menu=self, style=self.style)
        self.__items.append(item)
        self.__highlightedItem = None
        self.redraw()
        return item

    def addSeparator(self):
        item = Separator(menu=self, style=self.style)
        self.__items.append(item)
        self.__highlightedItem = None
        self.redraw()
        return item

    def popupOnScreen(self, screen, origin, parentMenu=None):
        if self.parent() is None:
            self.unload()
            self.__popup = True
            self.__autoExpand = True
            self.verticalLayout = True

            root = screen.frame
            root.addChild(self)
            self.load(screen)  # load font to calculate frame

            size = self.calculateFrameSize()
            sizeInPixel = self.convertLocalToPixel(size)
            sizeInRoot = root.convertPixelToLocal(sizeInPixel)

            origin.y -= sizeInRoot.height

            originInPixel = root.convertLocalToPixel(origin)
            originInPixel.x = math.floor(originInPixel.x + 0.5)
            originInPixel.y = math.floor(originInPixel.y + 0.5)
            originInRoot = root.convertPixelToLocal(originInPixel)

            frame = core.Rect(originInRoot, sizeInRoot)

            bounds = root.contentDisplayBounds()
            if frame.x < bounds.x:
                frame.x = bounds.x
            if frame.y < bounds.y:
                frame.y = bounds.y
            if frame.x + frame.width > bounds.x + bounds.width:
                frame.x = bounds.x + bounds.width - frame.width
            if frame.y + frame.height > bounds.y + bounds.height:
                frame.y = bounds.y + bounds.height - frame.height

            self.frame = frame
            self.redraw()

            if not isinstance(parentMenu, Menu):
                screen.postOperation(self._popupMouseSetup, ())
            return self

    def itemHitTest(self, pos):
        bounds = self.contentDisplayBounds()
        if bounds.isInside(pos):
            for item in self.__items:
                if item.hitTest(pos):
                    return item

    def popupHitTest(self, pos):
        if self.parent():
            if self.__popupChild:
                posInRoot = self.convertLocalToRoot(pos)
                posInLocal = self.__popupChild.convertRootToLocal(posInRoot)
                result = self.__popupChild.popupHitTest(posInLocal)
                if result:
                    return result

            bounds = self.contentDisplayBounds()
            if bounds.isInside(pos):
                return self

    def _popupMouseSetup(self):
        if self.__capturedMouseId is None:
            self.captureMouse(0)
            self.__capturedMouseId = 0
            self.__capturedMouseDown = False

    def onLoaded(self):
        super().onLoaded()
        self.style.font = self.font

    def onUnload(self):
        self.style.font = None
        self.__highlightedItem = None
        self.__selectedItem = None
        super().onUnload()

    def _calculatePopupFrameFromItem(self, item):
        parent = item.menu

        root = parent.screen().frame
        rect = item.displayRect

        bounds = root.contentDisplayBounds()

        size = self.calculateFrameSize()
        sizeInPixel = self.convertLocalToPixel(size)
        sizeInRoot = root.convertPixelToLocal(sizeInPixel)

        if parent.verticalLayout:
            left = parent.convertLocalToRoot(
                core.Point(rect.x, rect.y + rect.height))
            left.x -= sizeInRoot.width
            right = parent.convertLocalToRoot(
                core.Point(rect.x + rect.width, rect.y + rect.height))

            if right.x + sizeInRoot.width <= bounds.x + bounds.width:
                origin = right
            elif left.x >= bounds.x:
                origin = left
            else:
                d1 = (right.x + sizeInRoot.width) - (bounds.x + bounds.width)
                d2 = bounds.x - left.x
                origin = left if d1 > d2 else right
            origin.y -= sizeInRoot.height
        else:
            top = parent.convertLocalToRoot(
                core.Point(rect.x, rect.y + rect.height))
            bottom = parent.convertLocalToRoot(core.Point(rect.x, rect.y))
            bottom.y -= sizeInRoot.height

            if bottom.y >= bounds.y:
                origin = bottom
            elif top.y + size.height <= bounds.y + bounds.height:
                origin = top
            else:
                d1 = bounds.y - bottom.y
                d2 = (top.y + size.height) - (bounds.y + bounds.height)
                origin = top if d1 > d2 else bottom

        originInPixel = root.convertLocalToPixel(origin)
        originInPixel.x = math.floor(originInPixel.x + 0.5)
        originInPixel.y = math.floor(originInPixel.y + 0.5)
        origin = root.convertPixelToLocal(originInPixel)

        frame = core.Rect(origin, sizeInRoot)
        # frame.x = math.floor(frame.x * self.scaleFactor + 0.5) / self.scaleFactor
        # frame.y = math.floor(frame.y * self.scaleFactor + 0.5) / self.scaleFactor

        if frame.x < bounds.x:
            frame.x = bounds.x
        if frame.y < bounds.y:
            frame.y = bounds.y
        if frame.x + frame.width > bounds.x + bounds.width:
            frame.x = bounds.x + bounds.width - frame.width
        if frame.y + frame.height > bounds.y + bounds.height:
            frame.y = bounds.y + bounds.height - frame.height

        return frame

    def calculateFrameSize(self):
        style = self.style
        padding = self.itemPadding
        scale = 1.0 / self.scaleFactor
        numItems = len(self.__items)
        itemPadding = padding * (numItems - 1) if numItems > 0 else 0

        width = style.minimumWidth
        height = style.minimumHeight

        if self.__popup or self.verticalLayout:
            height = 0
            for item in self.__items:
                w, h = item.calculateFrameSize(_LAYOUT_VERTICAL, scale)
                width = max(width, w)
                height += h
            height = max(height + itemPadding, style.minimumHeight)
        else:
            width = 0
            for item in self.items():
                w, h = item.calculateFrameSize(_LAYOUT_HORIZONTAL, scale)
                width += w
                height = max(height, h)
            width = max(width + itemPadding, style.minimumWidth)

        width += self.margin * 2
        height += self.margin * 2
        return core.Size(width + self.borderWidth * 2,
                         height + self.borderWidth * 2)

    def getResolution(self):
        if self.isPopup():
            s = self.calculateFrameSize()
            self.contentScale = s
            return s.width * self.scaleFactor, s.height * self.scaleFactor
        return super().getResolution()

    def onRender(self, renderer):
        super().onRender(renderer)

        bounds = self.contentBounds()

        itemPadding = self.itemPadding
        offsetX = bounds.x + self.margin
        width = bounds.width - self.margin * 2
        height = bounds.height - self.margin * 2

        scale = 1.0 / self.scaleFactor
        state = _ITEM_STATE_NORMAL if self.enabled else _ITEM_STATE_DISABLED

        if self.__popup or self.verticalLayout:
            offsetY = bounds.y + bounds.height - self.margin
            for item in self.__items:
                w, h = item.calculateFrameSize(_LAYOUT_VERTICAL, scale)
                offsetY -= h
                rc = core.Rect(offsetX, offsetY, max(w, width), h)
                itemState = state
                if self.__highlightedItem == item and item.selectable(
                ) and itemState == _ITEM_STATE_NORMAL:
                    itemState = _ITEM_STATE_HIGHLIGHTED
                    with renderer.contextForSolidRects(
                            self.backgroundColorHighlighted) as r:
                        r.add(rc)
                item.drawRect(renderer, rc, itemState, _LAYOUT_VERTICAL)
                offsetY -= itemPadding
        else:
            offsetY = bounds.y + self.margin
            for item in self.__items:
                w, h = item.calculateFrameSize(_LAYOUT_HORIZONTAL, scale)
                rc = core.Rect(offsetX, offsetY, w, max(h, height))
                itemState = state
                if self.__highlightedItem == item and item.selectable(
                ) and itemState == _ITEM_STATE_NORMAL:
                    itemState = _ITEM_STATE_HIGHLIGHTED
                    with renderer.contextForSolidRects(
                            self.backgroundColorHighlighted) as r:
                        r.add(rc)
                item.drawRect(renderer, rc, itemState, _LAYOUT_HORIZONTAL)
                offsetX = offsetX + w + itemPadding

    def onUpdate(self, delta, tick, date):
        super().onUpdate(delta, tick, date)

    def updateLayout(self):
        if self.__popup:
            frame = self.frame
            frame.size = self.calculateFrameSize()
            self.frame = frame
        self.redraw()

    def isPopup(self):
        return self.__popup

    def dismiss(self):
        if self.__popupChild:
            self.__popupChild.dismiss()
        self.__popupChild = None
        self.__capturedMouseId = None
        self.__capturedMouseDown = False
        self.releaseAllMiceCapturedBySelf()
        if self.isPopup():
            self.removeFromParent(unload=True)
        else:
            self.__highlightedItem = None
            self.__autoExpand = False
            self.redraw()

    def setItemActivate(self, item):

        if not isinstance(item, Item) or not item.selectable():
            item = None

        if self.__highlightedItem != item:
            self.__highlightedItem = item
            self.redraw()

        if item and self.__autoExpand:
            menu = item.subMenu
            if menu:
                if self.__popupChild != menu:
                    if self.__popupChild:
                        self.screen().postOperation(self.__popupChild.dismiss,
                                                    ())
                    self.__popupChild = menu.popupOnScreen(
                        self.screen(), core.Point(0, 0), self)
                self.__popupChild.frame = self.__popupChild._calculatePopupFrameFromItem(
                    item)
            else:
                if self.__popupChild:
                    self.screen().postOperation(self.__popupChild.dismiss, ())
                    self.__popupChild = None

        elif self.__popupChild:
            self.screen().postOperation(self.__popupChild.dismiss, ())
            self.__popupChild = None

    def onMouseLeave(self, deviceId):
        super().onMouseLeave(deviceId)
        if deviceId == 0 and not self.isMouseCapturedBySelf(0):
            if self.__popupChild is None:
                if self.__highlightedItem:
                    self.__highlightedItem = None
                    self.redraw()

    def onMouseHover(self, deviceId):
        super().onMouseHover(deviceId)

    def onMouseDown(self, deviceId, buttonId, pos):
        super().onMouseDown(deviceId, buttonId, pos)

        if buttonId == 0:
            if not self.isPopup():
                item = self.itemHitTest(pos)
                if item and item.selectable():
                    if self.__capturedMouseId is None:
                        self.captureMouse(deviceId)
                        self.__capturedMouseId = deviceId
                        self.__capturedMouseDown = True
                        self.__autoExpand = True
                    else:
                        if self.__capturedMouseId == deviceId:
                            self.__autoExpand = not self.__autoExpand
                        elif not self.__capturedMouseDown:
                            self.captureMouse(deviceId)
                            self.__capturedMouseId = deviceId
                            self.__capturedMouseDown = True
                            self.__autoExpand = True

        item = None
        menu = self.popupHitTest(pos)
        if menu:
            if self.__capturedMouseId == deviceId and buttonId == 0:
                posInRoot = self.convertLocalToRoot(pos)
                posInLocal = menu.convertRootToLocal(posInRoot)
                item = menu.itemHitTest(posInLocal)
                if item:
                    menu.setItemActivate(item)
        else:
            self.screen().postOperation(self.dismiss, ())

    def onMouseUp(self, deviceId, buttonId, pos):
        super().onMouseUp(deviceId, buttonId, pos)

        if self.__capturedMouseId == deviceId and buttonId == 0:
            if self.isMouseCapturedBySelf(deviceId):
                menu = self.popupHitTest(pos)
                if menu:
                    posInRoot = self.convertLocalToRoot(pos)
                    posInLocal = menu.convertRootToLocal(posInRoot)
                    item = menu.itemHitTest(posInLocal)
                    if item and item.selectable():
                        if item.subMenu is None:
                            self.screen().postOperation(self.dismiss, ())
                            if item.callback:
                                self.screen().postOperation(
                                    item.callback, (item, ))

                self.__capturedMouseDown = False
                if not self.isPopup() and not self.__autoExpand:
                    hItem = self.__highlightedItem
                    self.dismiss()
                    self.__highlightedItem = hItem
            else:  # mouse lost?
                self.screen().postOperation(self.dismiss, ())

    def onMouseMove(self, deviceId, pos, delta):
        super().onMouseMove(deviceId, pos, delta)
        updateItem = False

        if self.__capturedMouseId == deviceId:
            if self.isMouseCapturedBySelf(deviceId):
                updateItem = True
            else:
                self.__capturedMouseId = None  # mouse lost?
        elif deviceId == 0 and self.__capturedMouseId is None:
            updateItem = True

        if updateItem:
            menu = self.popupHitTest(pos)
            if menu:
                posInRoot = self.convertLocalToRoot(pos)
                posInLocal = menu.convertRootToLocal(posInRoot)
                item = menu.itemHitTest(posInLocal)
                if item:
                    menu.setItemActivate(item)
            elif not self.__popupChild:
                self.setItemActivate(None)

    def onMouseLost(self, deviceId):
        super().onMouseLost(deviceId)
        self.screen().postOperation(self.dismiss, ())
예제 #27
0
파일: progress.py 프로젝트: DKGL/DKDemo
    def onRender(self, renderer):
        border = round(self.borderWidth)
        border2 = border * 2
        radius = round(self.cornerRadius)
        bounds = self.bounds()

        cornerRadius = min(radius,
                           math.floor(bounds.height * 0.5) - border,
                           math.floor(bounds.width * 0.5) - border)

        if cornerRadius > 1:
            texSize = (cornerRadius + border) * 2
            cornerRadius2 = cornerRadius * 2
            if self.__bsLayerMask1 is None:
                rt = rendertarget.RenderTarget(texSize * self.scaleFactor,
                                               texSize * self.scaleFactor,
                                               rendertarget.DEPTH_NONE)
                rd = Renderer(rt)
                rd.bounds = 0, 0, texSize, texSize
                rd.clear(core.Color(0, 0, 0, 0))
                with rd.contextForSolidEllipses(
                        core.Color(1, 1, 1,
                                   1), blend=blendstate.defaultOpaque) as r:
                    r.add(
                        core.Rect(border, border, cornerRadius2,
                                  cornerRadius2))
                self.__bsLayerMask1 = rt.colorTextureAtIndex(0)

            if border > 0:
                if self.__bsLayerMask2 is None:
                    rt = rendertarget.RenderTarget(texSize * self.scaleFactor,
                                                   texSize * self.scaleFactor,
                                                   rendertarget.DEPTH_NONE)
                    rd = Renderer(rt)
                    rd.bounds = 0, 0, texSize, texSize
                    rd.clear(core.Color(0, 0, 0, 0))
                    with rd.contextForSolidEllipses(
                            self.borderColor,
                            blend=blendstate.defaultOpaque) as r:
                        r.add(core.Rect(0, 0, texSize, texSize))
                    with rd.contextForSolidEllipses(
                            core.Color(0, 0, 0, 0),
                            blend=blendstate.defaultOpaque) as r:
                        r.add(
                            core.Rect(border, border, cornerRadius2,
                                      cornerRadius2))
                    self.__bsLayerMask2 = rt.colorTextureAtIndex(0)
            else:
                self.__bsLayerMask2 = None
        else:
            self.__bsLayerMask1 = None
            self.__bsLayerMask2 = None

        rc = core.Rect(bounds.x + border, bounds.y + border,
                       bounds.width - border2, bounds.height - border2)
        prog = self._progress / (self.maximumValue - self.minimumValue)
        if prog < 0.0: prog = 0.0
        if prog > 1.0: prog = 1.0
        if self.vertical:
            rc.height = rc.height * prog
        else:
            rc.width = rc.width * prog

        if border > 0:
            renderer.clear(self.borderColor)
            with renderer.contextForSolidRects(
                    self.progressColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

            if self.vertical:
                rc.y += rc.height
                rc.height = (bounds.height - border2) - rc.height
            else:
                rc.x += rc.width
                rc.width = (bounds.width - border2) - rc.width

            with renderer.contextForSolidRects(
                    self.backgroundColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

        else:
            renderer.clear(self.backgroundColor)
            with renderer.contextForSolidRects(
                    self.progressColor, blend=blendstate.defaultOpaque) as r:
                r.add(rc)

        if self.__bsLayerMask1:
            invScale = 1.0 / self.scaleFactor
            x = self.__bsLayerMask1.width * 0.5 * invScale
            y = self.__bsLayerMask1.height * 0.5 * invScale
            with renderer.contextForTexturedRects(
                    self.__bsLayerMask1, blend=blendstate.defaultDarken) as r:
                r.add(core.Rect(bounds.x, bounds.y, x, y), _identityMatrix3,
                      core.Rect(0, 0, 0.5, 0.5))
                r.add(core.Rect(bounds.x, bounds.y + bounds.height - y, x, y),
                      _identityMatrix3, core.Rect(0, 0.5, 0.5, 0.5))
                r.add(
                    core.Rect(bounds.x + bounds.width - x,
                              bounds.y + bounds.height - y, x, y),
                    _identityMatrix3, core.Rect(0.5, 0.5, 0.5, 0.5))
                r.add(core.Rect(bounds.x + bounds.width - x, bounds.y, x, y),
                      _identityMatrix3, core.Rect(0.5, 0.0, 0.5, 0.5))

            if self.__bsLayerMask2:
                x = self.__bsLayerMask2.width * 0.5 * invScale
                y = self.__bsLayerMask2.height * 0.5 * invScale
                with renderer.contextForTexturedRects(
                        self.__bsLayerMask2,
                        blend=blendstate.defaultAlpha) as r:
                    r.add(core.Rect(bounds.x, bounds.y, x, y),
                          _identityMatrix3, core.Rect(0, 0, 0.5, 0.5))
                    r.add(
                        core.Rect(bounds.x, bounds.y + bounds.height - y, x,
                                  y), _identityMatrix3,
                        core.Rect(0, 0.5, 0.5, 0.5))
                    r.add(
                        core.Rect(bounds.x + bounds.width - x,
                                  bounds.y + bounds.height - y, x, y),
                        _identityMatrix3, core.Rect(0.5, 0.5, 0.5, 0.5))
                    r.add(
                        core.Rect(bounds.x + bounds.width - x, bounds.y, x, y),
                        _identityMatrix3, core.Rect(0.5, 0.0, 0.5, 0.5))
예제 #28
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.setAmbientColor(core.Color(1, 1, 1, 1))
     self.drawMode = DRAW_MESHES
     self.lights = []
예제 #29
0
파일: menu.py 프로젝트: DKGL/DKDemo
class Item(_ItemContext):
    """
    Menu Item.

    if item has subMenu, item's callback will not invoked.
    """

    textColor = core.Color(0, 0, 0)
    outlineColor = None

    def __init__(self, text, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.callback = None
        self.subMenu = None
        self.__checked = False
        self.__text = text
        self.__enabled = True
        self.__image = None

    @property
    def enabled(self):
        return self.__enabled

    @enabled.setter
    def enabled(self, value):
        v = bool(value)
        if self.__enabled != v:
            self.__enabled = v
            menu = self.menu
            if menu:
                menu.redraw()

    @property
    def text(self):
        return self.__text

    @text.setter
    def text(self, value):
        text = str(value)
        if self.__text != text:
            self.__text = text
            menu = self.menu
            if menu:
                menu.updateLayout()

    @property
    def image(self):
        return self.__image

    @image.setter
    def image(self, value):
        self.__image = value
        menu = self.menu
        if menu:
            menu.updateLayout()

    @property
    def checked(self):
        return self.__checked

    @checked.setter
    def checked(self, value):
        self.__checked = bool(value)
        menu = self.menu
        if menu:
            menu.redraw()

    def selectable(self):
        '''
        determine whether item is selectable or not.
        items must be enabled, has subMenu or callable to be selectable.
        '''
        if self.enabled:
            if self.subMenu or self.callback:
                return True
        return super().selectable()

    def calculateFrameSize(self, layout, scale):
        style = self.style
        if style.font:
            h = style.font.textFont.lineHeight() * scale
            w = style.font.textFont.lineWidth(self.__text) * scale
            h += style.topMargin + style.bottomMargin
            w += style.checkmarkSize + style.padding + style.textMargin + style.arrowSize + style.leftMargin + style.rightMargin
            if self.__image:
                w += style.imageSize + style.padding
            return math.ceil(w), math.ceil(h)
        return self.style.minimumWidth, self.style.minimumHeight

    def drawRect(self, renderer, rect, state, layout):
        super().drawRect(renderer, rect, state, layout)

        style = self.style
        if style.font:
            if not self.selectable() or state == _ITEM_STATE_DISABLED:
                textColor = style.textColorDisabled
                outlineColor = style.outlineColorDisabled
                checkmarkColor = style.checkmarkColorDisabled
                arrowColor = style.arrowColorDisabled
            elif state == _ITEM_STATE_HIGHLIGHTED:
                textColor = style.textColorHighlighted
                outlineColor = style.outlineColorHighlighted
                checkmarkColor = style.checkmarkColorHighlighted
                arrowColor = style.arrowColorHighlighted
            else:
                textColor = style.textColor
                outlineColor = style.outlineColor
                checkmarkColor = style.checkmarkColor
                arrowColor = style.arrowColor

            rc = core.Rect(rect)
            rc.x += style.leftMargin
            rc.y += style.bottomMargin
            rc.width -= style.textMargin + style.arrowSize + style.leftMargin + style.rightMargin
            rc.height -= style.topMargin + style.bottomMargin

            if self.__checked:
                # draw check mark
                y = (rc.height - style.checkmarkSize) * 0.5
                cbRect = core.Rect(rc.x, rc.y + y, style.checkmarkSize,
                                   style.checkmarkSize)

                p0 = core.Point(0.15, 0.6)
                p1 = core.Point(0.05, 0.5)
                p2 = core.Point(0.4, 0.35)
                p3 = core.Point(0.4, 0.15)
                p4 = core.Point(0.85, 0.8)
                p5 = core.Point(0.95, 0.7)
                for p in (p0, p1, p2, p3, p4, p5):
                    p.x = p.x * cbRect.width + cbRect.x
                    p.y = p.y * cbRect.height + cbRect.y

                with renderer.contextForSolidTriangleStrip(
                        checkmarkColor, blend=blendstate.defaultOpaque) as r:
                    r.addTriangle(p0, p1, p2)
                    r.add(p3)
                    r.add(p4)
                    r.add(p5)

            offset = style.checkmarkSize + style.padding
            rc.x += offset
            rc.width -= offset

            if self.__image:
                y = (rc.height - style.imageSize) * 0.5
                rc2 = core.Rect(rc.x, rc.y + y, style.imageSize,
                                style.imageSize)
                with renderer.contextForTexturedRects(
                        self.__image, blend=blendstate.defaultAlpha) as r:
                    r.add(rc2, core.Matrix3())
                offset = style.imageSize + style.padding
                rc.x += offset
                rc.width -= offset

            font.drawText(renderer,
                          rc,
                          self.__text,
                          style.font,
                          textColor,
                          outlineColor,
                          align=font.ALIGN_BOTTOM_LEFT,
                          linebreak=font.LINE_BREAK_TRUNCATING_TAIL)

            #draw arrow!
            if self.subMenu:
                if layout == _LAYOUT_HORIZONTAL:
                    arRect = core.Rect(
                        rect.x + rect.width - style.arrowSize -
                        style.rightMargin, rect.y + style.bottomMargin,
                        style.arrowSize, style.arrowSize)
                    x1 = arRect.x
                    x2 = arRect.x + arRect.width * 0.5
                    x3 = arRect.x + arRect.width
                    y1 = arRect.y
                    y2 = arRect.y + arRect.height * 0.5
                    pos = (core.Point(x1,
                                      y2), core.Point(x2,
                                                      y1), core.Point(x3, y2))
                else:
                    y = (rc.height - style.arrowSize) * 0.5
                    arRect = core.Rect(
                        rect.x + rect.width - style.arrowSize -
                        style.rightMargin, rc.y + y, style.arrowSize,
                        style.arrowSize)

                    # x1 = arRect.x + arRect.width * 0.5
                    # x2 = arRect.x + arRect.width

                    w = arRect.height * 0.8660254037844388
                    x1 = arRect.x + (arRect.width - w) * 0.5
                    x2 = x1 + w

                    y1 = arRect.y
                    y2 = arRect.y + arRect.height * 0.5
                    y3 = arRect.y + arRect.height
                    pos = (core.Point(x1,
                                      y3), core.Point(x1,
                                                      y1), core.Point(x2, y2))

                if arrowColor:
                    with renderer.contextForSolidTriangles(
                            arrowColor, blend=blendstate.defaultOpaque) as r:
                        r.add(*pos)

        else:
            print('drawRect textFont is missing!!')