Example #1
0
 def value(self, path: str) -> None:
     """Set the current path. This calls the callback function."""
     import tooltip
     self.callback(path)
     self._location = path
     tooltip.set_tooltip(self, path)
     self._text_var.set(self._truncate(path))
Example #2
0
    def make_widgets(self, master: 'CheckDetails'):
        if self.master is not None:
            # If we let items move between lists, the old widgets will become
            # orphaned!
            raise ValueError(
                "Can't move Item objects between lists!"
            )

        self.master = master
        self.check = ttk.Checkbutton(
            master.wid_frame,
            variable=self.state_var,
            onvalue=1,
            offvalue=0,
            takefocus=False,
            width=0,
            style='CheckDetails.TCheckbutton',
            command=self.master.update_allcheck,
        )
        if self.locked:
            self.check.state(['disabled'])

        self.val_widgets = []
        for value in self.values:
            wid = tk.Label(
                master.wid_frame,
                text=value,
                justify=tk.LEFT,
                anchor=tk.W,
                background='white',
            )
            add_tooltip(wid)
            if self.hover_text:
                set_tooltip(wid, self.hover_text)
                wid.hover_override = True
            else:
                set_tooltip(wid)
                wid.hover_override = False

            if not self.locked:
                # Allow clicking on the row to toggle the checkbox
                wid.bind('<Enter>', self.hover_start, add='+')
                wid.bind('<Leave>', self.hover_stop, add='+')
                utils.bind_leftclick(wid, self.row_click, add='+')
                wid.bind(utils.EVENTS['LEFT_RELEASE'], self.row_unclick, add='+')

            self.val_widgets.append(wid)

        utils.add_mousewheel(
            self.master.wid_canvas,
            self.check,
            *self.val_widgets
        )
Example #3
0
    def make_widgets(self, master: 'CheckDetails'):
        if self.master is not None:
            # If we let items move between lists, the old widgets will become
            # orphaned!
            raise ValueError("Can't move Item objects between lists!")

        self.master = master
        self.check = ttk.Checkbutton(
            master.wid_frame,
            variable=self.state_var,
            onvalue=1,
            offvalue=0,
            takefocus=False,
            width=0,
            style='CheckDetails.TCheckbutton',
            command=self.master.update_allcheck,
        )
        if self.locked:
            self.check.state(['disabled'])

        self.val_widgets = []
        for value in self.values:
            wid = tk.Label(
                master.wid_frame,
                text=value,
                justify=tk.LEFT,
                anchor=tk.W,
                background='white',
            )
            add_tooltip(wid)
            if self.hover_text:
                set_tooltip(wid, self.hover_text)
                wid.hover_override = True
            else:
                set_tooltip(wid)
                wid.hover_override = False

            if not self.locked:
                # Allow clicking on the row to toggle the checkbox
                wid.bind('<Enter>', self.hover_start, add='+')
                wid.bind('<Leave>', self.hover_stop, add='+')
                utils.bind_leftclick(wid, self.row_click, add='+')
                wid.bind(utils.EVENTS['LEFT_RELEASE'],
                         self.row_unclick,
                         add='+')

            self.val_widgets.append(wid)

        utils.add_mousewheel(self.master.wid_canvas, self.check,
                             *self.val_widgets)
Example #4
0
    def readonly(self, value):
        self._readonly = bool(value)
        if self.display is None:
            # Widget hasn't been added yet, stop.
            # We update in the widget() method.
            return

        if value:
            new_st = ['disabled']
            set_tooltip(self.display, self.readonly_description)
        else:
            new_st = ['!disabled']
            set_tooltip(self.display, self.description)

        self.disp_btn.state(new_st)
        self.display.state(new_st)
Example #5
0
    def readonly(self, value):
        self._readonly = bool(value)
        if self.display is None:
            # Widget hasn't been added yet, stop.
            # We update in the widget() method.
            return

        if value:
            new_st = ['disabled']
            set_tooltip(self.display, self.readonly_description)
        else:
            new_st = ['!disabled']
            set_tooltip(self.display, self.description)

        self.disp_btn.state(new_st)
        self.display.state(new_st)
Example #6
0
 def place(self, check_width, head_pos, y):
     """Position the widgets on the frame."""
     self.check.place(
         x=0,
         y=y,
         width=check_width,
         height=ROW_HEIGHT,
     )
     for text, widget, (x, width) in zip(self.values, self.val_widgets,
                                         head_pos):
         widget.place(
             x=x + check_width,
             y=y,
             width=width,
             height=ROW_HEIGHT,
         )
         text = str(text)
         short_text = widget['text'] = truncate(text, width - 5)
         if not widget.hover_override:
             set_tooltip(widget, text if short_text != text else '')
         x += width
Example #7
0
def refresh_counts(reload=True):
    if reload:
        COMPILE_CFG.load()

    # Don't re-run the flash function if it's already on.
    run_flash = not (
        count_entity.should_flash or
        count_overlay.should_flash or
        count_brush.should_flash
    )

    for bar_var, name, default, tip_blurb in COUNT_CATEGORIES:
        value = COMPILE_CFG.get_int('Counts', name)

        if name == 'entity':
            # The in-engine entity limit is different to VBSP's limit
            # (that one might include prop_static, lights etc).
            max_value = default
        else:
            # Use or to ensure no divide-by-zero occurs..
            max_value = COMPILE_CFG.get_int('Counts', 'max_' + name) or default

        # If it's hit the limit, make it continously scroll to draw
        # attention to the bar.
        if value >= max_value:
            bar_var.should_flash = True
        else:
            bar_var.should_flash = False
            bar_var.set(100 * value / max_value)

        set_tooltip(UI['count_' + name], '{}/{} ({:.2%}):\n{}'.format(
            value,
            max_value,
            value / max_value,
            tip_blurb,
        ))

    if run_flash:
        flash_count()
Example #8
0
 def place(self, check_width, head_pos, y):
     """Position the widgets on the frame."""
     self.check.place(
         x=0,
         y=y,
         width=check_width,
         height=ROW_HEIGHT,
     )
     for text, widget, (x, width) in zip(
             self.values,
             self.val_widgets,
             head_pos
             ):
         widget.place(
             x=x+check_width,
             y=y,
             width=width,
             height=ROW_HEIGHT,
         )
         text = str(text)
         short_text = widget['text'] = truncate(text, width-5)
         if not widget.hover_override:
             set_tooltip(widget, text if short_text != text else '')
         x += width
Example #9
0
    def sel_item(self, item: Item, event=None):

        self.prop_name['text'] = item.longName
        if len(item.authors) == 0:
            self.prop_author['text'] = ''
        else:
            self.prop_author['text'] = ngettext(
                'Author: {}',
                'Authors: {}',
                len(item.authors),
            ).format(', '.join(item.authors))
        if item.large_icon is not None:
            # We have a large icon, use it.
            self.prop_icon['image'] = item.large_icon
            width, height = img.tuple_size(ICON_SIZE_LRG)
        else:
            # Small icon, shrink the preview.
            self.prop_icon['image'] = item.icon
            width, height = img.tuple_size(ICON_SIZE)
        self.prop_icon_frm.configure(width=width, height=height)

        self.prop_desc.set_text(item.desc)

        self.selected.button.state(('!alternate', ))
        self.selected = item
        item.button.state(('alternate', ))
        self.scroll_to(item)

        if self.sampler:
            is_playing = self.sampler.is_playing
            self.sampler.stop()

            self.sampler.cur_file = item.snd_sample
            if self.sampler.cur_file:
                self.samp_button.state(('!disabled', ))

                if is_playing:
                    # Start the sampler again, so it plays the current item!
                    self.sampler.play_sample()
            else:
                self.samp_button.state(('disabled', ))

        if self.has_def:
            if self.suggested is None or self.selected == self.suggested:
                self.prop_reset.state(('disabled', ))
            else:
                self.prop_reset.state(('!disabled', ))

        if self.attr:
            # Set the attribute items.
            for attr_id, label in self.attr.items():
                val = item.attrs.get(attr_id, label.default)

                if label.type is AttrTypes.BOOL:
                    label['image'] = (ICON_CHECK if val else ICON_CROSS)
                elif label.type is AttrTypes.COLOR:
                    label['image'] = img.color_square(val, size=16)
                    # Display the full color when hovering..
                    # i18n: Tooltip for colour swatch.
                    set_tooltip(
                        label,
                        _('Color: R={r}, G={g}, B={b}').format(
                            r=int(val.x),
                            g=int(val.y),
                            b=int(val.z),
                        ))
                elif label.type is AttrTypes.LIST:
                    # Join the values (in alphabetical order)
                    label['text'] = ', '.join(sorted(val))
                elif label.type is AttrTypes.STRING:
                    # Just a string.
                    label['text'] = str(val)
                else:
                    raise ValueError('Invalid attribute type: "{}"'.format(
                        label.type))
Example #10
0
def load_item_data():
    """Refresh the window to use the selected item's data."""
    global version_lookup
    item_data = selected_item.data

    for ind, pos in enumerate(SUBITEM_POS[selected_item.num_sub]):
        if pos == -1:
            wid['subitem', ind]['image'] = img.invis_square(64)
        else:
            wid['subitem', ind]['image'] = selected_item.get_icon(pos)
        wid['subitem', ind]['relief'] = 'flat'

    wid['subitem', pos_for_item()]['relief'] = 'raised'

    wid['author']['text'] = ', '.join(item_data.authors)
    wid['name']['text'] = selected_sub_item.name
    wid['ent_count']['text'] = item_data.ent_count or '??'

    wid['desc'].set_text(
        get_description(
            global_last=selected_item.item.glob_desc_last,
            glob_desc=selected_item.item.glob_desc,
            style_desc=item_data.desc,
        ))

    if itemPropWin.can_edit(selected_item.properties()):
        wid['changedefaults'].state(['!disabled'])
    else:
        wid['changedefaults'].state(['disabled'])

    version_lookup = set_version_combobox(wid['variant'], selected_item)

    if selected_item.url is None:
        wid['moreinfo'].state(['disabled'])
    else:
        wid['moreinfo'].state(['!disabled'])
    tooltip.set_tooltip(wid['moreinfo'], selected_item.url)

    editor_data = item_data.editor.copy()

    comm_block = Property(editor_data['Type'], [])
    (
        has_inputs,
        has_outputs,
        has_secondary,
    ) = packageLoader.Item.convert_item_io(comm_block, editor_data)
    del comm_block  # We don't use the config.

    has_timer = any(editor_data.find_all("Properties", "TimerDelay"))

    editor_bit = next(editor_data.find_all("Editor"))
    rot_type = editor_bit["MovementHandle", "HANDLE_NONE"].casefold()

    facing_type = editor_bit["InvalidSurface", ""].casefold()
    surf_wall = "wall" in facing_type
    surf_floor = "floor" in facing_type
    surf_ceil = "ceiling" in facing_type

    is_embed = any(editor_data.find_all("Exporting", "EmbeddedVoxels"))

    if has_inputs:
        if has_secondary:
            set_sprite(SPR.INPUT, 'in_dual')
            # Real funnels work slightly differently.
            if selected_item.id.casefold() == 'item_tbeam':
                wid['sprite', SPR.INPUT].tooltip_text = _(
                    'Excursion Funnels accept a on/off '
                    'input and a directional input.')
        else:
            set_sprite(SPR.INPUT, 'in_norm')
    else:
        set_sprite(SPR.INPUT, 'in_none')

    if has_outputs:
        if has_timer:
            set_sprite(SPR.OUTPUT, 'out_tim')
        else:
            set_sprite(SPR.OUTPUT, 'out_norm')
    else:
        set_sprite(SPR.OUTPUT, 'out_none')

    set_sprite(SPR.ROTATION, ROT_TYPES.get(
        rot_type.casefold(),
        'rot_none',
    ))

    if is_embed:
        set_sprite(SPR.COLLISION, 'space_embed')
    else:
        set_sprite(SPR.COLLISION, 'space_none')

    face_spr = "surf"
    if not surf_wall:
        face_spr += "_wall"
    if not surf_floor:
        face_spr += "_floor"
    if not surf_ceil:
        face_spr += "_ceil"
    if face_spr == "surf":
        # This doesn't seem right - this item won't be placeable at all...
        LOGGER.warning(
            "Item <{}> disallows all orientations. Is this right?",
            selected_item.id,
        )
        face_spr += "_none"

    set_sprite(SPR.FACING, face_spr)

    # Now some special overrides for certain classes.
    if selected_item.id == "ITEM_CUBE":
        # Cubes - they should show info for the dropper.
        set_sprite(SPR.FACING, 'surf_ceil')
        set_sprite(SPR.INPUT, 'in_norm')
        set_sprite(SPR.COLLISION, 'space_embed')
        set_sprite(SPR.OUTPUT, 'out_none')
        set_sprite(SPR.ROTATION, 'rot_36')
        tooltip.set_tooltip(
            wid['sprite', SPR.ROTATION],
            SPRITE_TOOL['rot_36'] +
            _('This item can be rotated on the floor to face 360 '
              'degrees, for Reflection Cubes only.'),
        )

    item_class = editor_data['ItemClass', ''].casefold()
    if item_class == "itempaintsplat":
        # Reflection or normal gel..
        set_sprite(SPR.FACING, 'surf_wall_ceil')
        set_sprite(SPR.INPUT, 'in_norm')
        set_sprite(SPR.COLLISION, 'space_none')
        set_sprite(SPR.OUTPUT, 'out_none')
        set_sprite(SPR.ROTATION, 'rot_paint')
    elif item_class == 'itemrailplatform':
        # Track platform - always embeds into the floor.
        set_sprite(SPR.COLLISION, 'space_embed')
Example #11
0
def set_sprite(pos, sprite):
    """Set one of the property sprites to a value."""
    widget = wid['sprite', pos]
    widget['image'] = img.spr(sprite)
    tooltip.set_tooltip(widget, SPRITE_TOOL.get(sprite, ''))
Example #12
0
def load_item_data():
    """Refresh the window to use the selected item's data."""
    global version_lookup
    item_data = selected_item.data

    for ind, pos in enumerate(SUBITEM_POS[selected_item.num_sub]):
        if pos == -1:
            wid['subitem', ind]['image'] = img.invis_square(64)
        else:
            wid['subitem', ind]['image'] = selected_item.get_icon(pos)
        wid['subitem', ind]['relief'] = 'flat'

    wid['subitem', pos_for_item()]['relief'] = 'raised'

    wid['author']['text'] = ', '.join(item_data.authors)
    wid['name']['text'] = selected_sub_item.name
    wid['ent_count']['text'] = item_data.ent_count or '??'

    wid['desc'].set_text(
        get_description(
            global_last=selected_item.item.glob_desc_last,
            glob_desc=selected_item.item.glob_desc,
            style_desc=item_data.desc,
        )
    )

    if itemPropWin.can_edit(selected_item.properties()):
        wid['changedefaults'].state(['!disabled'])
    else:
        wid['changedefaults'].state(['disabled'])

    version_lookup = set_version_combobox(wid['variant'], selected_item)

    if selected_item.url is None:
        wid['moreinfo'].state(['disabled'])
    else:
        wid['moreinfo'].state(['!disabled'])
    tooltip.set_tooltip(wid['moreinfo'], selected_item.url)

    editor_data = item_data.editor.copy()

    comm_block = Property(selected_item.id, [])
    (
        has_inputs,
        has_outputs,
        has_secondary,
    ) = packageLoader.Item.convert_item_io(comm_block, editor_data)
    del comm_block  # We don't use the config.

    has_timer = any(editor_data.find_all("Properties", "TimerDelay"))

    editor_bit = next(editor_data.find_all("Editor"))
    rot_type = editor_bit["MovementHandle", "HANDLE_NONE"].casefold()

    facing_type = editor_bit["InvalidSurface", ""].casefold()
    surf_wall = "wall" in facing_type
    surf_floor = "floor" in facing_type
    surf_ceil = "ceiling" in facing_type

    is_embed = any(editor_data.find_all("Exporting", "EmbeddedVoxels"))

    if has_inputs:
        if has_secondary:
            set_sprite(SPR.INPUT, 'in_dual')
            # Real funnels work slightly differently.
            if selected_item.id.casefold() == 'item_tbeam':
                wid['sprite', SPR.INPUT].tooltip_text = _(
                    'Excursion Funnels accept a on/off '
                    'input and a directional input.'
                )
        else:
            set_sprite(SPR.INPUT, 'in_norm')
    else:
        set_sprite(SPR.INPUT, 'in_none')

    if has_outputs:
        if has_timer:
            set_sprite(SPR.OUTPUT, 'out_tim')
        else:
            set_sprite(SPR.OUTPUT, 'out_norm')
    else:
        set_sprite(SPR.OUTPUT, 'out_none')

    set_sprite(
        SPR.ROTATION,
        ROT_TYPES.get(
            rot_type.casefold(),
            'rot_none',
        )
    )

    if is_embed:
        set_sprite(SPR.COLLISION, 'space_embed')
    else:
        set_sprite(SPR.COLLISION, 'space_none')

    face_spr = "surf"
    if not surf_wall:
        face_spr += "_wall"
    if not surf_floor:
        face_spr += "_floor"
    if not surf_ceil:
        face_spr += "_ceil"
    if face_spr == "surf":
        # This doesn't seem right - this item won't be placeable at all...
        LOGGER.warning(
            "Item <{}> disallows all orientations. Is this right?",
            selected_item.id,
        )
        face_spr += "_none"

    set_sprite(SPR.FACING, face_spr)

    # Now some special overrides for certain classes.
    if selected_item.id == "ITEM_CUBE":
        # Cubes - they should show info for the dropper.
        set_sprite(SPR.FACING, 'surf_ceil')
        set_sprite(SPR.INPUT, 'in_norm')
        set_sprite(SPR.COLLISION, 'space_embed')
        set_sprite(SPR.OUTPUT, 'out_none')
        set_sprite(SPR.ROTATION, 'rot_36')
        tooltip.set_tooltip(
            wid['sprite', SPR.ROTATION],
            SPRITE_TOOL['rot_36'] + _(
                'This item can be rotated on the floor to face 360 '
                'degrees, for Reflection Cubes only.'
            ),
        )

    item_class = editor_data['ItemClass', ''].casefold()
    if item_class == "itempaintsplat":
        # Reflection or normal gel..
        set_sprite(SPR.FACING, 'surf_wall_ceil')
        set_sprite(SPR.INPUT, 'in_norm')
        set_sprite(SPR.COLLISION, 'space_none')
        set_sprite(SPR.OUTPUT, 'out_none')
        set_sprite(SPR.ROTATION, 'rot_paint')
    elif item_class == 'itemrailplatform':
        # Track platform - always embeds into the floor.
        set_sprite(SPR.COLLISION, 'space_embed')
Example #13
0
def set_sprite(pos, sprite):
    """Set one of the property sprites to a value."""
    widget = wid['sprite', pos]
    widget['image'] = img.spr(sprite)
    tooltip.set_tooltip(widget, SPRITE_TOOL.get(sprite, ''))
Example #14
0
    def sel_item(self, item: Item, event=None):

        self.prop_name['text'] = item.longName
        if len(item.authors) == 0:
            self.prop_author['text'] = ''
        else:
            self.prop_author['text'] = ngettext(
                'Author: {}', 'Authors: {}', len(item.authors),
            ).format(
                ', '.join(item.authors)
            )
        if item.large_icon is not None:
            # We have a large icon, use it.
            self.prop_icon['image'] = item.large_icon
            width, height = img.tuple_size(ICON_SIZE_LRG)
        else:
            # Small icon, shrink the preview.
            self.prop_icon['image'] = item.icon
            width, height = img.tuple_size(ICON_SIZE)
        self.prop_icon_frm.configure(width=width, height=height)

        self.prop_desc.set_text(item.desc)

        self.selected.button.state(('!alternate',))
        self.selected = item
        item.button.state(('alternate',))
        self.scroll_to(item)

        if self.sampler:
            is_playing = self.sampler.is_playing
            self.sampler.stop()

            self.sampler.cur_file = item.snd_sample
            if self.sampler.cur_file:
                self.samp_button.state(('!disabled',))

                if is_playing:
                    # Start the sampler again, so it plays the current item!
                    self.sampler.play_sample()
            else:
                self.samp_button.state(('disabled',))

        if self.has_def:
            if self.suggested is None or self.selected == self.suggested:
                self.prop_reset.state(('disabled',))
            else:
                self.prop_reset.state(('!disabled',))

        if self.attr:
            # Set the attribute items.
            for attr_id, label in self.attr.items():
                val = item.attrs.get(attr_id, label.default)

                if label.type is AttrTypes.BOOL:
                    label['image'] = (
                        ICON_CHECK
                        if val else
                        ICON_CROSS
                    )
                elif label.type is AttrTypes.COLOR:
                    label['image'] = img.color_square(val, size=16)
                    # Display the full color when hovering..
                    # i18n: Tooltip for colour swatch.
                    set_tooltip(label, _('Color: R={r}, G={g}, B={b}').format(
                        r=int(val.x), g=int(val.y), b=int(val.z),
                    ))
                elif label.type is AttrTypes.LIST:
                    # Join the values (in alphabetical order)
                    label['text'] = ', '.join(sorted(val))
                elif label.type is AttrTypes.STRING:
                    # Just a string.
                    label['text'] = str(val)
                else:
                    raise ValueError(
                        'Invalid attribute type: "{}"'.format(label.type)
                    )