Пример #1
0
def add_tabs():
    """Add the tabs to the notebook."""
    notebook = UI['tabs']
    # Save the current tab index so we can restore it after.
    try:
        current_tab = notebook.index(notebook.select())
    except TclError:  # .index() will fail if the voice is empty,
        current_tab = None  # in that case abandon remembering the tab.

    # Add or remove tabs so only the correct mode is visible.
    for name, tab in sorted(TABS.items()):
        notebook.add(tab)
        # For the special tabs, we use a special image to make
        # sure they are well-distinguished from the other groups
        if tab.nb_type is TabTypes.MID:
            notebook.tab(
                tab,
                compound='image',
                image=img.png('icons/mid_quote'),
            )
        if tab.nb_type is TabTypes.RESPONSE:
            notebook.tab(
                tab,
                compound=RIGHT,
                image=img.png('icons/resp_quote'),
                #Note: 'response' tab name, should be short.
                text=_('Resp'))
        else:
            notebook.tab(tab, text=tab.nb_text)

    if current_tab is not None:
        notebook.select(current_tab)
Пример #2
0
def add_tabs():
    """Add the tabs to the notebook."""
    notebook = UI['tabs']
    # Save the current tab index so we can restore it after.
    try:
        current_tab = notebook.index(notebook.select())
    except TclError:  # .index() will fail if the voice is empty,
        current_tab = None  # in that case abandon remembering the tab.

    # Add or remove tabs so only the correct mode is visible.
    for name, tab in sorted(TABS.items()):
        notebook.add(tab)
        # For the special tabs, we use a special image to make
        # sure they are well-distinguished from the other groups
        if tab.nb_type is TabTypes.MID:
            notebook.tab(
                tab,
                compound='image',
                image=img.png('icons/mid_quote'),
                )
        if tab.nb_type is TabTypes.RESPONSE:
            notebook.tab(
                tab,
                compound=RIGHT,
                image=img.png('icons/resp_quote'),
                text='Resp'
                )
        else:
            notebook.tab(tab, text=tab.nb_text)

    if current_tab is not None:
        notebook.select(current_tab)
Пример #3
0
 def __init__(
     self,
     name: str,
     icon: str,
     group: str=None,
     group_icon: str=None,
 ) -> None:
     self.name = name
     self.dnd_icon = img.png('items/clean/{}.png'.format(icon))
     self.dnd_group = group
     if group_icon:
         self.dnd_group_icon = img.png('items/clean/{}.png'.format(group_icon))
Пример #4
0
def set_corridors(config: Dict[Tuple[str, int], CorrDesc]):
    """Set the corridor data based on the passed in config."""
    CORRIDOR_DATA.clear()
    CORRIDOR_DATA.update(config)

    default_icon = img.icon('clean/portal_door')

    corridor_conf = COMPILE_CFG['CorridorNames']

    for group, length in CORRIDOR_COUNTS.items():
        selector = CORRIDOR[group]
        for item in selector.item_list:
            if item.name == '<NONE>':
                continue  # No customisation for this.
            ind = int(item.name)

            data = config[group, ind]

            corridor_conf['{}_{}_name'.format(group, ind)] = data.name
            corridor_conf['{}_{}_desc'.format(group, ind)] = data.desc
            corridor_conf['{}_{}_icon'.format(group, ind)] = data.icon

            # Note: default corridor description
            desc = data.name or _('Corridor')
            item.longName = item.shortName = item.context_lbl = item.name + ': ' + desc

            if data.icon:
                item.large_icon = img.png(
                    'corr/' + data.icon,
                    resize_to=selectorWin.ICON_SIZE_LRG,
                    error=default_icon,
                )
                item.icon = img.png(
                    'corr/' + data.icon,
                    resize_to=selectorWin.ICON_SIZE,
                    error=default_icon,
                )
            else:
                item.icon = item.large_icon = default_icon

            if data.desc:
                item.desc = tkMarkdown.convert(data.desc)
            else:
                item.desc = CORRIDOR_DESC

        selector.set_disp()

    COMPILE_CFG.save_check()
Пример #5
0
def make_help_menu(parent: tk.Menu):
    """Create the application 'Help' menu."""
    # Using this name displays this correctly in OS X
    help = tk.Menu(parent, name='help')

    parent.add_cascade(menu=help, label=_('Help'))

    invis_icon = img.invis_square(16)
    icons = {
        icon: img.png('icons/' + icon.value, resize_to=16, error=invis_icon)
        for icon in ResIcon if icon is not ResIcon.NONE
    }
    icons[ResIcon.NONE] = invis_icon

    credits = Dialog(
        title=_('BEE2 Credits'),
        text=CREDITS_TEXT,
    )

    for res in WEB_RESOURCES:
        if res is SEPERATOR:
            help.add_separator()
        else:
            help.add_command(
                label=res.name,
                command=functools.partial(webbrowser.open, res.url),
                compound='left',
                image=icons[res.icon],
            )

    help.add_separator()
    help.add_command(
        label=_('Credits...'),
        command=credits.show,
    )
Пример #6
0
def style_changed(new_style: Style) -> None:
    """Update the icons for the selected signage."""
    for sign in Signage.all():
        if sign.hidden:
            # Don't bother with making the icon.
            continue

        for potential_style in new_style.bases:
            try:
                icon = sign.styles[potential_style.id.upper()].icon
                break
            except KeyError:
                pass
        else:
            LOGGER.warning(
                'No valid <{}> style for "{}" signage!',
                new_style.id,
                sign.id,
            )
            try:
                icon = sign.styles['BEE2_CLEAN'].icon
            except KeyError:
                sign.dnd_icon = img.img_error
                continue
        if icon:
            sign.dnd_icon = img.png(icon, resize_to=(64, 64))
        else:
            LOGGER.warning(
                'No icon for "{}" signage in <{}> style!',
                sign.id,
                new_style.id,
            )
            sign.dnd_icon = img.img_error
    drag_man.refresh_icons()
Пример #7
0
    def __init__(
            self,
            name: str,
            short_name: str,
            long_name: str=None,
            icon=None,
            authors: list=None,
            desc=(('line', ''),),
            group: str=None,
            sort_key: str=None,
            attributes: dict=None,
            snd_sample: str=None,
    ):
        self.name = name
        self.shortName = short_name
        self.group = group or ''
        self.longName = long_name or short_name
        self.sort_key = sort_key
        if len(self.longName) > 20:
            self.context_lbl = self.shortName
        else:
            self.context_lbl = self.longName
        if icon is None:
            self.icon = img.png(
                'BEE2/blank_96',
                error=err_icon,
                resize_to=ICON_SIZE,
            )
            self.ico_file = 'BEE2/blank_96'
        else:
            self.icon = img.png(
                icon,
                error=err_icon,
                resize_to=ICON_SIZE,
            )
            self.ico_file = icon
        self.desc = desc
        self.snd_sample = snd_sample
        self.authors = authors or []
        self.attrs = attributes or {}
        self.button = None  # type: ttk.Button
        self.win = None  # type: Toplevel

        self.win_x = None  # type: int
        self.win_y = None  # type: int
Пример #8
0
def refresh(e=None):
    notebook = UI['tabs']
    is_coop = coop_selected

    # Save the current tab index so we can restore it after.
    try:
        current_tab = notebook.index(notebook.select())
    except TclError:  # .index() will fail if the voice is empty,
        current_tab = None  # in that case abandon remembering the tab.

    # Add or remove tabs so only the correct mode is visible.
    for name, tab in sorted(TABS_SP.items()):
        if is_coop:
            notebook.forget(tab)
        else:
            notebook.add(tab)
            if tab.nb_is_mid:
                # For the midpoint tabs, we use a special image to make
                # sure they are well-distinguished from the other groups.
                notebook.tab(
                    tab,
                    compound='image',
                    image=img.png('icons/mid_quote'),
                    )
            else:
                notebook.tab(tab, text=tab.nb_text)

    for name, tab in sorted(TABS_COOP.items()):
        if is_coop:
            notebook.add(tab)
            if tab.nb_is_mid:
                notebook.tab(
                    tab,
                    compound='image',
                    image=img.png('icons/mid_quote'),
                    )
            else:
                notebook.tab(tab, text=tab.nb_text)

        else:
            notebook.forget(tab)

    if current_tab is not None:
        notebook.select(current_tab)
Пример #9
0
    def __init__(
        self,
        man: Manager,
        parent: tkinter.Misc,
        is_source: bool,
        label: str,
    ) -> None:
        """Internal only, use Manager.slot()."""

        self.man = man
        self.is_source = is_source
        self._contents: Optional[ItemT] = None
        self._pos_type: Optional[str] = None
        self._lbl = tkinter.Label(
            parent,
            image=man._img_blank,
        )
        utils.bind_leftclick(self._lbl, self._evt_start)
        self._lbl.bind(utils.EVENTS['LEFT_SHIFT'], self._evt_fastdrag)
        self._lbl.bind('<Enter>', self._evt_hover_enter)
        self._lbl.bind('<Leave>', self._evt_hover_exit)

        config_event = self._evt_configure
        utils.bind_rightclick(self._lbl, config_event)

        if label:
            self._text_lbl = tkinter.Label(
                self._lbl,
                text=label,
                font=('Helvetica', -12),
                relief='ridge',
                bg=img.PETI_ITEM_BG_HEX,
            )
        else:
            self._text_lbl = None

        if man.config_icon:
            self._info_btn = tkinter.Label(
                self._lbl,
                image=img.png('icons/gear'),
                relief='ridge',
            )

            @utils.bind_leftclick(self._info_btn)
            def info_button_click(e):
                """Trigger the callback whenever the gear button was pressed."""
                config_event(e)
                # Cancel the event sequence, so it doesn't travel up to the main
                # window and hide the window again.
                return 'break'
            # Rightclick does the same as the main icon.
            utils.bind_rightclick(self._info_btn, config_event)
        else:
            self._info_btn = None
Пример #10
0
def get_icon(icon, size, err_icon):
    if icon is None:
        # Unset.
        return None
    elif icon == '<black>':
        return img.color_square(Vec(), size)
    else:
        return img.png(
            icon,
            error=err_icon,
            resize_to=size,
            algo=img.Image.LANCZOS,
        )
Пример #11
0
def get_icon(icon, size, err_icon):
    if icon is None:
        # Unset.
        return None
    elif icon == '<black>':
        return img.color_square(Vec(), size)
    else:
        return img.png(
            icon,
            error=err_icon,
            resize_to=size,
            algo=img.Image.LANCZOS,
        )
Пример #12
0
def refresh(e=None):
    notebook = UI['tabs']
    is_coop = coop_selected

    # Save the current tab index so we can restore it after.
    current_tab = notebook.index(notebook.select())

    # Add or remove tabs so only the correct mode is visible.
    for name, tab in sorted(TABS_SP.items()):
        if is_coop:
            notebook.forget(tab)
        else:
            notebook.add(tab)
            if tab.nb_is_mid:
                # For the midpoint tabs, we use a special image to make
                # sure they are well-distinguished from the other groups.
                notebook.tab(
                    tab,
                    compound='image',
                    image=img.png('icons/mid_quote'),
                    )
            else:
                notebook.tab(tab, text=tab.nb_text)

    for name, tab in sorted(TABS_COOP.items()):
        if is_coop:
            notebook.add(tab)
            if tab.nb_is_mid:
                notebook.tab(
                    tab,
                    compound='image',
                    image=img.png('icons/mid_quote'),
                    )
            else:
                notebook.tab(tab, text=tab.nb_text)

        else:
            notebook.forget(tab)
    notebook.select(current_tab)
Пример #13
0
 def __init__(
         self,
         name: str,
         short_name: str,
         long_name: str=None,
         icon=None,
         authors: list=None,
         desc=(('line', ''),),
         group: str=None,
         attributes: dict=None,
         ):
     self.name = name
     self.shortName = short_name
     self.group = group
     self.longName = long_name or short_name
     if len(self.longName) > 20:
         self.context_lbl = self.shortName
     else:
         self.context_lbl = self.longName
     if icon is None:
         self.icon = img.png(
             'BEE2/blank_96',
             error=err_icon,
             resize_to=ICON_SIZE,
         )
         self.ico_file = 'BEE2/blank_96'
     else:
         self.icon = img.png(
             icon,
             error=err_icon,
             resize_to=ICON_SIZE,
         )
         self.ico_file = icon
     self.desc = desc
     self.authors = authors or []
     self.attrs = attributes or {}
     self.button = None
     self.win = None
Пример #14
0
 def __init__(
         self,
         name,
         short_name,
         long_name=None,
         icon=None,
         authors=None,
         desc=(('line', ''),),
         group=None,
         ):
     self.name = name
     self.shortName = short_name
     self.group = group
     self.longName = long_name or short_name
     if len(self.longName) > 20:
         self.context_lbl = self.shortName
     else:
         self.context_lbl = self.longName
     if icon is None:
         self.icon = img.png(
             'BEE2/blank_96',
             error=err_icon,
             resize_to=ICON_SIZE,
         )
         self.ico_file = 'BEE2/blank_96'
     else:
         self.icon = img.png(
             icon,
             error=err_icon,
             resize_to=ICON_SIZE,
         )
         self.ico_file = icon
     self.desc = desc
     self.authors = [] if authors is None else authors
     self.button = None
     self.win = None
Пример #15
0
def make_pane(tool_frame):
    """Initialise when part of the BEE2."""
    global window
    window = SubPane.SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title=_('Compile Options'),
        name='compiler',
        resize_x=True,
        resize_y=False,
        tool_frame=tool_frame,
        tool_img=img.png('icons/win_compiler'),
        tool_col=4,
    )
    window.columnconfigure(0, weight=1)
    window.rowconfigure(0, weight=1)
    make_widgets()
Пример #16
0
    def set_text(self, text_data: Union[str, tkMarkdown.MarkdownData]):
        """Write the rich-text into the textbox.

        text_data should either be a string, or the data returned from
        tkMarkdown.convert().
        """

        # Remove all previous link commands
        for tag, (command_id, func) in self.link_commands.items():
            self.tag_unbind(tag, '<Button-1>', funcid=command_id)
        self.link_commands.clear()

        self['state'] = "normal"
        self.delete(1.0, END)

        # Basic mode, insert just blocks of text.
        if isinstance(text_data, str):
            super().insert("end", text_data)
            return

        for block_type, block_data in text_data.blocks:
            if block_type is tkMarkdown.BlockTags.TEXT:
                super().insert('end', *block_data)
            elif block_type is tkMarkdown.BlockTags.IMAGE:
                super().insert('end', '\n')
                self.image_create('end', image=img.png(block_data))
                super().insert('end', '\n')
            else:
                raise ValueError('Unknown block {!r}?'.format(block_type))

        for url, link_id in text_data.links.items():
            func = self.make_link_callback(url)
            self.link_commands[link_id] = self.tag_bind(
                link_id,
                '<Button-1>',
                self.make_link_callback(url),
            ), func

        self['state'] = "disabled"
Пример #17
0
    def set_text(self, text_data: Union[str, tkMarkdown.MarkdownData]):
        """Write the rich-text into the textbox.

        text_data should either be a string, or the data returned from
        tkMarkdown.convert().
        """

        # Remove all previous link commands
        for tag, (command_id, func) in self.link_commands.items():
            self.tag_unbind(tag, '<Button-1>', funcid=command_id)
        self.link_commands.clear()

        self['state'] = "normal"
        self.delete(1.0, END)

        # Basic mode, insert just blocks of text.
        if isinstance(text_data, str):
            super().insert("end", text_data)
            return

        for block_type, block_data in text_data.blocks:
            if block_type is tkMarkdown.BlockTags.TEXT:
                super().insert('end', *block_data)
            elif block_type is tkMarkdown.BlockTags.IMAGE:
                super().insert('end', '\n')
                self.image_create('end', image=img.png(block_data))
                super().insert('end', '\n')
            else:
                raise ValueError('Unknown block {!r}?'.format(block_type))

        for url, link_id in text_data.links.items():
            func = self.make_link_callback(url)
            self.link_commands[link_id] = self.tag_bind(
                link_id,
                '<Button-1>',
                self.make_link_callback(url),
            ), func

        self['state'] = "disabled"
Пример #18
0
from richTextBox import tkRichText
from tooltip import add_tooltip
import sound
import utils
import tk_tools

from typing import Callable

LOGGER = utils.getLogger(__name__)

ICON_SIZE = 96  # Size of the selector win icons
ITEM_WIDTH = ICON_SIZE + (32 if utils.MAC else 16)
ITEM_HEIGHT = ICON_SIZE + 51

# The larger error icon used if an image is not found
err_icon = img.png('BEE2/error_96', resize_to=ICON_SIZE)

# The two icons used for boolean item attributes
ICON_CHECK = img.png('icons/check')
ICON_CROSS = img.png('icons/cross')

# Arrows used to indicate the state of the group - collapsed or expanded
GRP_COLL = '◁'
GRP_COLL_HOVER = '◀'
GRP_EXP = '▽'
GRP_EXP_HOVER = '▼'

BTN_PLAY = '▶'
BTN_STOP = '■'

Пример #19
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'] = png.png('BEE2/alpha_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['auth'])
    wid['name']['text'] = selected_sub_item.name
    wid['ent_count']['text'] = item_data['ent']

    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'])

    if selected_item.is_wip and selected_item.is_dep:
        wid['wip_dep']['text'] = 'WIP, Deprecated Item!'
    elif selected_item.is_wip:
        wid['wip_dep']['text'] = 'WIP Item!'
    elif selected_item.is_dep:
        wid['wip_dep']['text'] = 'Deprecated Item!'
    else:
        wid['wip_dep']['text'] = ''

    version_lookup, version_names = selected_item.get_version_names()
    if len(version_names) <= 1:
        # There aren't any alternates to choose from, disable the box
        wid['variant'].state(['disabled'])
        # We want to display WIP / Dep tags still, so users know.
        if selected_item.is_wip and selected_item.is_dep:
            wid['variant']['values'] = ['[WIP] [DEP] No Alts!']
        elif selected_item.is_wip:
            wid['variant']['values'] = ['[WIP] No Alt Versions!']
        elif selected_item.is_dep:
            wid['variant']['values'] = ['[DEP] No Alt Versions!']
        else:
            wid['variant']['values'] = ['No Alternate Versions!']
        wid['variant'].current(0)
    else:
        wid['variant'].state(['!disabled'])
        wid['variant']['values'] = version_names
        wid['variant'].current(version_lookup.index(selected_item.selected_ver))

    if selected_item.url is None:
        wid['moreinfo'].state(['disabled'])
    else:
        wid['moreinfo'].state(['!disabled'])
    wid['moreinfo'].tooltip_text = selected_item.url

    editor_data = item_data['editor']

    has_inputs = False
    has_polarity = False
    has_outputs = False
    for inp_list in editor_data.find_all("Exporting", "Inputs"):
        for inp in inp_list:
            if inp.name == "connection_standard":
                has_inputs = True
            elif inp.name == "connection_tbeam_polarity":
                has_polarity = True
    for out_list in editor_data.find_all("Exporting", "Outputs"):
        for out in out_list:
            if out.name == "connection_standard":
                has_outputs = True
                break
    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_polarity:
            set_sprite(SPR.INPUT, 'in_polarity')
        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 paint and cube dropper items..
    if selected_item.id == "ITEM_CUBE":
        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')
        wid['sprite', SPR.ROTATION].tooltip_text += '\n(Reflection Cube only)'

    if editor_data['ItemClass', ''].casefold() == "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')
Пример #20
0
import srctools.logger
from srctools.filesys import FileSystemChain
import tkMarkdown
import sound
import utils
import tk_tools

LOGGER = srctools.logger.get_logger(__name__)

ICON_SIZE = 96  # Size of the selector win icons
ICON_SIZE_LRG = (256, 192)  # Size of the larger icon shown in description.
ITEM_WIDTH = ICON_SIZE + (32 if utils.MAC else 16)
ITEM_HEIGHT = ICON_SIZE + 51

# The larger error icons used if an image is not found
err_icon = img.png('BEE2/error_96', resize_to=ICON_SIZE)
err_icon_lrg = img.png('BEE2/error_96', resize_to=ICON_SIZE_LRG)

# The two icons used for boolean item attributes
ICON_CHECK = img.png('icons/check')
ICON_CROSS = img.png('icons/cross')

# Arrows used to indicate the state of the group - collapsed or expanded
GRP_COLL = '◁'
GRP_COLL_HOVER = '◀'
GRP_EXP = '▽'
GRP_EXP_HOVER = '▼'

BTN_PLAY = '▶'
BTN_STOP = '■'
Пример #21
0
def init_widgets():
    """Initiallise all the window components."""
    global prop_window, moreinfo_win
    prop_window = Toplevel(TK_ROOT)
    prop_window.overrideredirect(1)
    prop_window.resizable(False, False)
    prop_window.transient(master=TK_ROOT)
    prop_window.attributes('-topmost', 1)
    prop_window.relX = 0
    prop_window.relY = 0
    prop_window.withdraw()  # starts hidden

    f = ttk.Frame(prop_window, relief="raised", borderwidth="4")
    f.grid(row=0, column=0)

    ttk.Label(
        f,
        text="Properties:",
        anchor="center",
        ).grid(
            row=0,
            column=0,
            columnspan=3,
            sticky="EW",
            )

    wid['name'] = ttk.Label(f, text="", anchor="center")
    wid['name'].grid(row=1, column=0, columnspan=3, sticky="EW")

    wid['ent_count'] = ttk.Label(
        f,
        text="2",
        anchor="e",
        compound="left",
        image=png.spr('gear_ent'),
        )
    wid['ent_count'].grid(row=0, column=2, rowspan=2, sticky=E)

    wid['author'] = ttk.Label(f, text="", anchor="center", relief="sunken")
    wid['author'].grid(row=2, column=0, columnspan=3, sticky="EW")

    sub_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    sub_frame.grid(column=0, columnspan=3, row=3)
    for i, _ in enumerate(wid['subitem']):
        wid['subitem'][i] = ttk.Label(
            sub_frame,
            image=png.png('BEE2/alpha_64'),
        )
        wid['subitem'][i].grid(row=0, column=i)
        wid['subitem'][i].bind('<Button-1>', functools.partial(sub_sel, i))
        wid['subitem'][i].bind('<Button-3>', functools.partial(sub_open, i))

    wid['wip_dep'] = ttk.Label(f, text='', anchor="nw")
    wid['wip_dep'].grid(row=4, column=0, sticky="NW")

    ttk.Label(f, text="Description:", anchor="sw").grid(
        row=4,
        column=0,
        sticky="SW",
        )

    spr_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    spr_frame.grid(column=1, columnspan=2, row=4, sticky=W)
    # sprites: inputs, outputs, rotation handle, occupied/embed state,
    # desiredFacing
    for i in range(5):
        spr = png.spr('ap_grey')
        wid['sprite'][i] = ttk.Label(spr_frame, image=spr, relief="raised")
        wid['sprite'][i].grid(row=0, column=i)

    desc_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    desc_frame.grid(row=5, column=0, columnspan=3, sticky="EW")

    wid['desc'] = tkRichText(desc_frame, width=40, height=8, font=None)
    wid['desc'].grid(row=0, column=0, sticky="EW")

    desc_scroll = ttk.Scrollbar(
        desc_frame,
        orient=VERTICAL,
        command=wid['desc'].yview,
        )
    wid['desc']['yscrollcommand'] = desc_scroll.set
    desc_scroll.grid(row=0, column=1, sticky="NS")

    def show_more_info():
        url = selected_item.url
        if url is not None:
            try:
                webbrowser.open(url, new=OPEN_IN_TAB, autoraise=True)
            except webbrowser.Error:
                if messagebox.askyesno(
                        icon="error",
                        title="BEE2 - Error",
                        message='Failed to open a web browser. Do you wish for '
                                'the URL to be copied to the clipboard '
                                'instead?',
                        detail='"{!s}"'.format(url),
                        parent=prop_window
                        ):
                    print("Saving " + url + "to clipboard!")
                    TK_ROOT.clipboard_clear()
                    TK_ROOT.clipboard_append(url)
            # Either the webbrowser or the messagebox could cause the
            # properties to move behind the main window, so hide it
            # so it doesn't appear there.
            hide_context(None)

    wid['moreinfo'] = ttk.Button(f, text="More Info>>", command=show_more_info)
    wid['moreinfo'].grid(row=6, column=2, sticky=E)
    wid['moreinfo'].bind('<Enter>', more_info_show_url)
    wid['moreinfo'].bind('<Leave>', more_info_hide_url)

    moreinfo_win = Toplevel(TK_ROOT)
    moreinfo_win.withdraw()
    moreinfo_win.transient(master=TK_ROOT)
    moreinfo_win.overrideredirect(1)
    moreinfo_win.resizable(False, False)

    wid['moreinfo_context'] = ttk.Label(
        moreinfo_win,
        text='',
        relief="groove",
        font="TkSmallCaptionFont",
        padding=(5, 2),
        )
    wid['moreinfo_context'].grid(row=0, column=0)

    menu_info = Menu(wid['moreinfo'])
    menu_info.add_command(label='', state='disabled')

    def show_item_props():
        snd.fx('expand')
        itemPropWin.show_window(
            selected_item.get_properties(),
            wid['changedefaults'],
            selected_sub_item.name,
        )

    wid['changedefaults'] = ttk.Button(
        f,
        text="Change Defaults...",
        command=show_item_props,
        )
    wid['changedefaults'].grid(row=6, column=1)

    wid['variant'] = ttk.Combobox(f, values=['VERSION'], exportselection=0)
    wid['variant'].state(['readonly'])  # Prevent directly typing in values
    wid['variant'].bind('<<ComboboxSelected>>', set_item_version)
    wid['variant'].current(0)
    wid['variant'].grid(row=6, column=0, sticky=W)

    itemPropWin.init(hide_item_props)
Пример #22
0
def make_comp_widgets(frame: ttk.Frame):
    """Create widgets for the compiler settings pane.

    These are generally things that are aesthetic, and to do with the file and
    compilation process.
    """
    frame.columnconfigure(0, weight=1)

    thumb_frame = ttk.LabelFrame(
        frame,
        text=_('Thumbnail'),
        labelanchor=N,
    )
    thumb_frame.grid(row=0, column=0, sticky=EW)
    thumb_frame.columnconfigure(0, weight=1)

    UI['thumb_auto'] = ttk.Radiobutton(
        thumb_frame,
        text=_('Auto'),
        value='AUTO',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_peti'] = ttk.Radiobutton(
        thumb_frame,
        text=_('PeTI'),
        value='PETI',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_custom'] = ttk.Radiobutton(
        thumb_frame,
        text=_('Custom:'),
        value='CUST',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_label'] = ttk.Label(
        thumb_frame,
        anchor=CENTER,
        cursor=utils.CURSORS['link'],
    )
    UI['thumb_label'].bind(
        utils.EVENTS['LEFT'],
        find_screenshot,
    )

    UI['thumb_cleanup'] = ttk.Checkbutton(
        thumb_frame,
        text=_('Cleanup old screenshots'),
        variable=cleanup_screenshot,
        command=make_setter('Screenshot', 'del_old', cleanup_screenshot),
    )

    UI['thumb_auto'].grid(row=0, column=0, sticky='W')
    UI['thumb_peti'].grid(row=0, column=1, sticky='W')
    UI['thumb_custom'].grid(row=1, column=0, columnspan=2, sticky='NEW')
    UI['thumb_cleanup'].grid(row=3, columnspan=2, sticky='W')
    add_tooltip(
        UI['thumb_auto'],
        _("Override the map image to use a screenshot automatically taken "
          "from the beginning of a chamber. Press F5 to take a new "
          "screenshot. If the map has not been previewed recently "
          "(within the last few hours), the default PeTI screenshot "
          "will be used instead.")
    )
    add_tooltip(
        UI['thumb_peti'],
        _("Use the normal editor view for the map preview image.")
    )
    custom_tooltip = _(
        "Use a custom image for the map preview image. Click the "
        "screenshot to select.\n"
        "Images will be converted to JPEGs if needed."
    )
    add_tooltip(
        UI['thumb_custom'],
        custom_tooltip,
    )

    add_tooltip(
        UI['thumb_label'],
        custom_tooltip,
    )

    add_tooltip(
        UI['thumb_cleanup'],
        _('Automatically delete unused Automatic screenshots. '
          'Disable if you want to keep things in "portal2/screenshots". ')
    )

    if chosen_thumb.get() == 'CUST':
        # Show this if the user has set it before
        UI['thumb_label'].grid(row=2, column=0, columnspan=2, sticky='EW')
    set_screenshot()  # Load the last saved screenshot

    vrad_frame = ttk.LabelFrame(
        frame,
        text=_('Lighting:'),
        labelanchor=N,
    )
    vrad_frame.grid(row=1, column=0, sticky=EW)

    UI['light_fast'] = ttk.Radiobutton(
        vrad_frame,
        text=_('Fast'),
        value=0,
        variable=vrad_light_type,
        command=make_setter('General', 'vrad_force_full', vrad_light_type),
    )
    UI['light_fast'].grid(row=0, column=0)
    UI['light_full'] = ttk.Radiobutton(
        vrad_frame,
        text=_('Full'),
        value=1,
        variable=vrad_light_type,
        command=make_setter('General', 'vrad_force_full', vrad_light_type),
    )
    UI['light_full'].grid(row=0, column=1)

    add_tooltip(
        UI['light_fast'],
        _("Compile with lower-quality, fast lighting. This speeds "
          "up compile times, but does not appear as good. Some "
          "shadows may appear wrong.\n"
          "When publishing, this is ignored.")
    )
    add_tooltip(
        UI['light_full'],
        _("Compile with high-quality lighting. This looks correct, "
          "but takes longer to compute. Use if you're arranging lights. "
          "When publishing, this is always used.")
    )

    packfile_enable = ttk.Checkbutton(
        frame,
        text=_('Dump packed files to:'),
        variable=packfile_dump_enable,
        command=set_pack_dump_enabled,
    )

    packfile_frame = ttk.LabelFrame(
        frame,
        labelwidget=packfile_enable,
    )
    packfile_frame.grid(row=2, column=0, sticky=EW)

    UI['packfile_filefield'] = packfile_filefield = FileField(
        packfile_frame,
        is_dir=True,
        loc=COMPILE_CFG.get_val('General', 'packfile_dump_dir', ''),
        callback=set_pack_dump_dir,
    )
    packfile_filefield.grid(row=0, column=0, sticky=EW)
    packfile_frame.columnconfigure(0, weight=1)
    ttk.Frame(packfile_frame).grid(row=1)

    set_pack_dump_enabled()

    add_tooltip(
        packfile_enable,
        _("When compiling, dump all files which were packed into the map. Useful"
          " if you're intending to edit maps in Hammer.")
    )

    count_frame = ttk.LabelFrame(
        frame,
        text=_('Last Compile:'),
        labelanchor=N,
    )

    count_frame.grid(row=7, column=0, sticky=EW)
    count_frame.columnconfigure(0, weight=1)
    count_frame.columnconfigure(2, weight=1)

    ttk.Label(
        count_frame,
        text=_('Entity'),
        anchor=N,
    ).grid(row=0, column=0, columnspan=3, sticky=EW)

    UI['count_entity'] = ttk.Progressbar(
        count_frame,
        maximum=100,
        variable=count_entity,
        length=120,
    )
    UI['count_entity'].grid(
        row=1,
        column=0,
        columnspan=3,
        sticky=EW,
        padx=5,
    )

    ttk.Label(
        count_frame,
        text=_('Overlay'),
        anchor=CENTER,
    ).grid(row=2, column=0, sticky=EW)
    UI['count_overlay'] = ttk.Progressbar(
        count_frame,
        maximum=100,
        variable=count_overlay,
        length=50,
    )
    UI['count_overlay'].grid(row=3, column=0, sticky=EW, padx=5)

    UI['refresh_counts'] = SubPane.make_tool_button(
        count_frame,
        img.png('icons/tool_sub', resize_to=16),
        refresh_counts,
    )
    UI['refresh_counts'].grid(row=3, column=1)
    add_tooltip(
        UI['refresh_counts'],
        _("Refresh the compile progress bars. Press after a compile has been "
          "performed to show the new values."),
    )

    ttk.Label(
        count_frame,
        text=_('Brush'),
        anchor=CENTER,
    ).grid(row=2, column=2, sticky=EW)
    UI['count_brush'] = ttk.Progressbar(
        count_frame,
        maximum=100,
        variable=count_brush,
        length=50,
    )
    UI['count_brush'].grid(row=3, column=2, sticky=EW, padx=5)

    for wid_name in ('count_overlay', 'count_entity', 'count_brush'):
        # Add in tooltip logic to the widgets.
        add_tooltip(UI[wid_name])

    refresh_counts(reload=False)
Пример #23
0
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=BEE2_config.GEN_OPTS,
        title=_('Style/Item Properties'),
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=img.png('icons/win_stylevar'),
        tool_col=3,
    )

    UI['nbook'] = nbook = ttk.Notebook(window)

    nbook.grid(row=0, column=0, sticky=NSEW)
    window.rowconfigure(0, weight=1)
    window.columnconfigure(0, weight=1)
    nbook.enable_traversal()

    stylevar_frame = ttk.Frame(nbook)
    stylevar_frame.rowconfigure(0, weight=1)
    stylevar_frame.columnconfigure(0, weight=1)
    nbook.add(stylevar_frame, text=_('Styles'))

    UI['style_can'] = Canvas(stylevar_frame, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        stylevar_frame,
        orient=VERTICAL,
        command=UI['style_can'].yview,
        )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set

    utils.add_mousewheel(UI['style_can'], stylevar_frame)

    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text=_("All:"))
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text=_("Selected Style:"))
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
        ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text=_("Other Styles:"))
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text=_('No Options!'),
        font='TkMenuFont',
        justify='center',
        )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text=_('None!'),
        font='TkMenuFont',
        justify='center',
        )

    all_pos = 0
    for all_pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = int_var = IntVar(value=var.default)
        checkbox_all[var.id] = ttk.Checkbutton(
            frame_all,
            variable=int_var,
            text=var.name,
        )
        checkbox_all[var.id].grid(row=all_pos, column=0, sticky="W", padx=3)

        # Special case - this needs to refresh the filter when swapping,
        # so the items disappear or reappear.
        if var.id == 'UnlockDefault':
            def cmd():
                update_filter()
            checkbox_all[var.id]['command'] = cmd

        tooltip.add_tooltip(
            checkbox_all[var.id],
            make_desc(var, is_hardcoded=True),
        )

    for var in VAR_LIST:
        tk_vars[var.id] = IntVar(value=var.enabled)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            }
        desc = make_desc(var)
        if var.applies_to_all():
            # Available in all styles - put with the hardcoded variables.
            all_pos += 1

            checkbox_all[var.id] = check = ttk.Checkbutton(frame_all, **args)
            check.grid(row=all_pos, column=0, sticky="W", padx=3)
            tooltip.add_tooltip(check, desc)
        else:
            # Swap between checkboxes depending on style.
            checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
            checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
            tooltip.add_tooltip(
                checkbox_chosen[var.id],
                desc,
            )
            tooltip.add_tooltip(
                checkbox_other[var.id],
                desc,
            )

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
    )

    if utils.USE_SIZEGRIP:
        ttk.Sizegrip(
            window,
            cursor=utils.CURSORS['stretch_vert'],
        ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)

    item_config_frame = ttk.Frame(nbook)
    nbook.add(item_config_frame, text=_('Items'))
    itemconfig.make_pane(item_config_frame)
Пример #24
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'] = png.png('BEE2/alpha_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['auth'])
    wid['name']['text'] = selected_sub_item.name
    wid['ent_count']['text'] = item_data['ent']

    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'])

    if selected_item.is_wip and selected_item.is_dep:
        wid['wip_dep']['text'] = 'WIP, Deprecated Item!'
    elif selected_item.is_wip:
        wid['wip_dep']['text'] = 'WIP Item!'
    elif selected_item.is_dep:
        wid['wip_dep']['text'] = 'Deprecated Item!'
    else:
        wid['wip_dep']['text'] = ''

    version_lookup, version_names = selected_item.get_version_names()
    if len(version_names) <= 1:
        # There aren't any alternates to choose from, disable the box
        wid['variant'].state(['disabled'])
        # We want to display WIP / Dep tags still, so users know.
        if selected_item.is_wip and selected_item.is_dep:
            wid['variant']['values'] = ['[WIP] [DEP] No Alts!']
        elif selected_item.is_wip:
            wid['variant']['values'] = ['[WIP] No Alt Versions!']
        elif selected_item.is_dep:
            wid['variant']['values'] = ['[DEP] No Alt Versions!']
        else:
            wid['variant']['values'] = ['No Alternate Versions!']
        wid['variant'].current(0)
    else:
        wid['variant'].state(['!disabled'])
        wid['variant']['values'] = version_names
        wid['variant'].current(version_lookup.index(
            selected_item.selected_ver))

    if selected_item.url is None:
        wid['moreinfo'].state(['disabled'])
    else:
        wid['moreinfo'].state(['!disabled'])
    wid['moreinfo'].tooltip_text = selected_item.url

    editor_data = item_data['editor']
    has_inputs = False
    has_polarity = False
    has_outputs = False
    for inp_list in editor_data.find_all("Exporting", "Inputs"):
        for inp in inp_list:
            if inp.name == "CONNECTION_STANDARD":
                has_inputs = True
            elif inp.name == "CONNECTION_TBEAM_POLARITY":
                has_polarity = True
    for out_list in editor_data.find_all("Exporting", "Outputs"):
        for out in out_list:
            if out.name == "CONNECTION_STANDARD":
                has_outputs = True
                break
    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_polarity:
            wid['sprite'][0]['image'] = png.spr('in_polarity')
        else:
            wid['sprite'][0]['image'] = png.spr('in_norm')
    else:
        wid['sprite'][0]['image'] = png.spr('in_none')

    if has_outputs:
        if has_timer:
            wid['sprite'][1]['image'] = png.spr('out_tim')
        else:
            wid['sprite'][1]['image'] = png.spr('out_norm')
    else:
        wid['sprite'][1]['image'] = png.spr('out_none')

    wid['sprite'][2]['image'] = png.spr(
        ROT_TYPES.get(
            rot_type.casefold(),
            'rot_none',
        ))

    if is_embed:
        wid['sprite'][3]['image'] = png.spr('space_embed')
    else:
        wid['sprite'][3]['image'] = png.spr('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":
        face_spr += "_none"
    wid['sprite'][4]['image'] = png.spr(face_spr)
Пример #25
0
from BEE2_config import ConfigFile
from srctools import Property
from tk_tools import TK_ROOT

LOGGER = utils.getLogger(__name__)

voice_item = None

UI = {}

TABS = {}

QUOTE_FONT = font.nametofont('TkHeadingFont').copy()
QUOTE_FONT['weight'] = 'bold'

SP_IMG = img.png('icons/quote_sp')
COOP_IMG = img.png('icons/quote_coop')

# Friendly names given to certain response channels.
RESPONSE_NAMES = {
    'death_goo': _('Death - Toxic Goo'),
    'death_turret': _('Death - Turrets'),
    'death_crush': _('Death - Crusher'),
    'death_laserfield': _('Death - LaserField'),
}

config = config_mid = config_resp = None  # type: ConfigFile


class TabTypes(Enum):
    NORM = 0
Пример #26
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'] = png.png('BEE2/alpha_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['auth'])
    wid['name']['text'] = selected_sub_item.name
    wid['ent_count']['text'] = item_data['ent']

    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'])

    if selected_item.is_wip and selected_item.is_dep:
        wid['wip_dep']['text'] = 'WIP, Deprecated Item!'
    elif selected_item.is_wip:
        wid['wip_dep']['text'] = 'WIP Item!'
    elif selected_item.is_dep:
        wid['wip_dep']['text'] = 'Deprecated Item!'
    else:
        wid['wip_dep']['text'] = ''

    version_lookup, version_names = selected_item.get_version_names()
    if len(version_names) <= 1:
        # There aren't any alternates to choose from, disable the box
        wid['variant'].state(['disabled'])
        # We want to display WIP / Dep tags still, so users know.
        if selected_item.is_wip and selected_item.is_dep:
            wid['variant']['values'] = ['[WIP] [DEP] No Alts!']
        elif selected_item.is_wip:
            wid['variant']['values'] = ['[WIP] No Alt Versions!']
        elif selected_item.is_dep:
            wid['variant']['values'] = ['[DEP] No Alt Versions!']
        else:
            wid['variant']['values'] = ['No Alternate Versions!']
        wid['variant'].current(0)
    else:
        wid['variant'].state(['!disabled'])
        wid['variant']['values'] = version_names
        wid['variant'].current(version_lookup.index(selected_item.selected_ver))

    if selected_item.url is None:
        wid['moreinfo'].state(['disabled'])
    else:
        wid['moreinfo'].state(['!disabled'])
    wid['moreinfo'].tooltip_text = selected_item.url

    editor_data = item_data['editor']
    has_inputs = False
    has_polarity = False
    has_outputs = False
    for inp_list in editor_data.find_all("Exporting", "Inputs"):
        for inp in inp_list:
            if inp.name == "connection_standard":
                has_inputs = True
            elif inp.name == "connection_tbeam_polarity":
                has_polarity = True
    for out_list in editor_data.find_all("Exporting", "Outputs"):
        for out in out_list:
            if out.name == "connection_standard":
                has_outputs = True
                break
    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_polarity:
            wid['sprite'][0]['image'] = png.spr('in_polarity')
        else:
            wid['sprite'][0]['image'] = png.spr('in_norm')
    else:
        wid['sprite'][0]['image'] = png.spr('in_none')

    if has_outputs:
        if has_timer:
            wid['sprite'][1]['image'] = png.spr('out_tim')
        else:
            wid['sprite'][1]['image'] = png.spr('out_norm')
    else:
        wid['sprite'][1]['image'] = png.spr('out_none')

    wid['sprite'][2]['image'] = png.spr(
        ROT_TYPES.get(
            rot_type.casefold(),
            'rot_none',
        )
    )

    if is_embed:
        wid['sprite'][3]['image'] = png.spr('space_embed')
    else:
        wid['sprite'][3]['image'] = png.spr('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":
        face_spr += "_none"
    wid['sprite'][4]['image'] = png.spr(face_spr)
Пример #27
0
QUOTE_FONT = font.nametofont('TkHeadingFont').copy()
QUOTE_FONT['weight'] = 'bold'

IMG_TEXT = {
    'sp': _('Singleplayer'),
    'coop': _('Cooperative'),
    'atlas': _('ATLAS (SP/Coop)'),
    'pbody': _('P-Body (SP/Coop)'),
    'bendy': _('Bendy'),
    'chell': _('Chell'),
    'human': _('Human characters (Bendy and Chell)'),
    'robot': _('AI characters (ATLAS, P-Body, or Coop)'),
}

IMG = {
    spr: (img.png('icons/quote_' + spr), ctx)
    for spr, ctx in IMG_TEXT.items()
}  # type: Dict[str, Tuple[PhotoImage, str]]


# Friendly names given to certain response channels.
RESPONSE_NAMES = {
    'death_goo': _('Death - Toxic Goo'),
    'death_turret': _('Death - Turrets'),
    'death_crush': _('Death - Crusher'),
    'death_laserfield': _('Death - LaserField'),
}

config = config_mid = config_resp = None  # type: ConfigFile

Пример #28
0
def init():
    """Initialise all widgets in the given window."""
    for cat, btn_text in [
            ('back_', 'Restore:'),
            ('game_', 'Backup:'),
            ]:
        UI[cat + 'frame'] = frame = ttk.Frame(
            window,
        )
        UI[cat + 'title_frame'] = title_frame = ttk.Frame(
            frame,
        )
        title_frame.grid(row=0, column=0, sticky='EW')
        UI[cat + 'title'] = ttk.Label(
            title_frame,
            font='TkHeadingFont',
        )
        UI[cat + 'title'].grid(row=0, column=0)
        title_frame.rowconfigure(0, weight=1)
        title_frame.columnconfigure(0, weight=1)

        UI[cat + 'details'] = CheckDetails(
            frame,
            headers=HEADERS,
        )
        UI[cat + 'details'].grid(row=1, column=0, sticky='NSEW')
        frame.rowconfigure(1, weight=1)
        frame.columnconfigure(0, weight=1)

        button_frame = ttk.Frame(
            frame,
        )
        button_frame.grid(column=0, row=2)
        ttk.Label(button_frame, text=btn_text).grid(row=0, column=0)
        UI[cat + 'btn_all'] = ttk.Button(
            button_frame,
            text='All',
            width=3,
        )
        UI[cat + 'btn_sel'] = ttk.Button(
            button_frame,
            text='Checked',
            width=8,
        )
        UI[cat + 'btn_all'].grid(row=0, column=1)
        UI[cat + 'btn_sel'].grid(row=0, column=2)

        UI[cat + 'btn_del'] = ttk.Button(
            button_frame,
            text='Delete Checked',
            width=14,
        )
        UI[cat + 'btn_del'].grid(row=1, column=0, columnspan=3)

        utils.add_mousewheel(
            UI[cat + 'details'].wid_canvas,
            UI[cat + 'frame'],
        )

    UI['game_refresh'] = ttk.Button(
        UI['game_title_frame'],
        image=img.png('icons/tool_sub'),
        command=ui_refresh_game,
    )
    UI['game_refresh'].grid(row=0, column=1, sticky='E')
    add_tooltip(
        UI['game_refresh'],
        "Reload the map list.",
    )

    UI['game_title']['textvariable'] = game_name
    UI['back_title']['textvariable'] = backup_name

    UI['game_btn_all']['command'] = ui_backup_all
    UI['game_btn_sel']['command'] = ui_backup_sel

    UI['back_btn_all']['command'] = ui_restore_all
    UI['back_btn_sel']['command'] = ui_restore_sel

    UI['back_frame'].grid(row=1, column=0, sticky='NSEW')
    ttk.Separator(orient=tk.VERTICAL).grid(
        row=1, column=1, sticky='NS', padx=5,
    )
    UI['game_frame'].grid(row=1, column=2, sticky='NSEW')

    window.rowconfigure(1, weight=1)
    window.columnconfigure(0, weight=1)
    window.columnconfigure(2, weight=1)
Пример #29
0
QUOTE_FONT = font.nametofont('TkHeadingFont').copy()
QUOTE_FONT['weight'] = 'bold'

IMG_TEXT = {
    'sp': _('Singleplayer'),
    'coop': _('Cooperative'),
    'atlas': _('ATLAS (SP/Coop)'),
    'pbody': _('P-Body (SP/Coop)'),
    'bendy': _('Bendy'),
    'chell': _('Chell'),
    'human': _('Human characters (Bendy and Chell)'),
    'robot': _('AI characters (ATLAS, P-Body, or Coop)'),
}

IMG = {
    spr: (img.png('icons/quote_' + spr), ctx)
    for spr, ctx in IMG_TEXT.items()
}  # type: Dict[str, Tuple[PhotoImage, str]]

# Friendly names given to certain response channels.
RESPONSE_NAMES = {
    'death_goo': _('Death - Toxic Goo'),
    'death_turret': _('Death - Turrets'),
    'death_crush': _('Death - Crusher'),
    'death_laserfield': _('Death - LaserField'),
}

config = config_mid = config_resp = None  # type: ConfigFile


class TabTypes(Enum):
Пример #30
0
def init_widgets():
    """Initiallise all the window components."""
    global prop_window, moreinfo_win
    prop_window = Toplevel(TK_ROOT)
    prop_window.overrideredirect(1)
    prop_window.resizable(False, False)
    prop_window.transient(master=TK_ROOT)
    prop_window.attributes('-topmost', 1)
    prop_window.relX = 0
    prop_window.relY = 0
    prop_window.withdraw()  # starts hidden

    f = ttk.Frame(prop_window, relief="raised", borderwidth="4")
    f.grid(row=0, column=0)

    ttk.Label(
        f,
        text="Properties:",
        anchor="center",
    ).grid(
        row=0,
        column=0,
        columnspan=3,
        sticky="EW",
    )

    wid['name'] = ttk.Label(f, text="", anchor="center")
    wid['name'].grid(row=1, column=0, columnspan=3, sticky="EW")

    wid['ent_count'] = ttk.Label(
        f,
        text="2",
        anchor="e",
        compound="left",
        image=png.spr('gear_ent'),
    )
    wid['ent_count'].grid(row=0, column=2, rowspan=2, sticky=E)

    wid['author'] = ttk.Label(f, text="", anchor="center", relief="sunken")
    wid['author'].grid(row=2, column=0, columnspan=3, sticky="EW")

    sub_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    sub_frame.grid(column=0, columnspan=3, row=3)
    for i, _ in enumerate(wid['subitem']):
        wid['subitem'][i] = ttk.Label(
            sub_frame,
            image=png.png('BEE2/alpha_64'),
        )
        wid['subitem'][i].grid(row=0, column=i)
        utils.bind_leftclick(
            wid['subitem'][i],
            functools.partial(sub_sel, i),
        )
        utils.bind_rightclick(
            wid['subitem'][i],
            functools.partial(sub_open, i),
        )

    wid['wip_dep'] = ttk.Label(f, text='', anchor="nw")
    wid['wip_dep'].grid(row=4, column=0, sticky="NW")

    ttk.Label(f, text="Description:", anchor="sw").grid(
        row=4,
        column=0,
        sticky="SW",
    )

    spr_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    spr_frame.grid(column=1, columnspan=2, row=4, sticky=W)
    # sprites: inputs, outputs, rotation handle, occupied/embed state,
    # desiredFacing
    for i in range(5):
        spr = png.spr('ap_grey')
        wid['sprite'][i] = ttk.Label(spr_frame, image=spr, relief="raised")
        wid['sprite'][i].grid(row=0, column=i)

    desc_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    desc_frame.grid(row=5, column=0, columnspan=3, sticky="EW")
    desc_frame.columnconfigure(0, weight=1)

    wid['desc'] = tkRichText(desc_frame, width=40, height=8, font=None)
    wid['desc'].grid(row=0, column=0, sticky="EW")

    desc_scroll = ttk.Scrollbar(
        desc_frame,
        orient=VERTICAL,
        command=wid['desc'].yview,
    )
    wid['desc']['yscrollcommand'] = desc_scroll.set
    desc_scroll.grid(row=0, column=1, sticky="NS")

    def show_more_info():
        url = selected_item.url
        if url is not None:
            try:
                webbrowser.open(url, new=OPEN_IN_TAB, autoraise=True)
            except webbrowser.Error:
                if messagebox.askyesno(
                        icon="error",
                        title="BEE2 - Error",
                        message='Failed to open a web browser. Do you wish for '
                        'the URL to be copied to the clipboard '
                        'instead?',
                        detail='"{!s}"'.format(url),
                        parent=prop_window):
                    print("Saving " + url + "to clipboard!")
                    TK_ROOT.clipboard_clear()
                    TK_ROOT.clipboard_append(url)
            # Either the webbrowser or the messagebox could cause the
            # properties to move behind the main window, so hide it
            # so it doesn't appear there.
            hide_context(None)

    wid['moreinfo'] = ttk.Button(f, text="More Info>>", command=show_more_info)
    wid['moreinfo'].grid(row=6, column=2, sticky=E)
    tooltip.add_tooltip(wid['moreinfo'])

    menu_info = Menu(wid['moreinfo'])
    menu_info.add_command(label='', state='disabled')

    def show_item_props():
        snd.fx('expand')
        itemPropWin.show_window(
            selected_item.get_properties(),
            wid['changedefaults'],
            selected_sub_item.name,
        )

    wid['changedefaults'] = ttk.Button(
        f,
        text="Change Defaults...",
        command=show_item_props,
    )
    wid['changedefaults'].grid(row=6, column=1)
    tooltip.add_tooltip(
        wid['changedefaults'],
        'Change the default settings for this item when placed.')

    wid['variant'] = ttk.Combobox(
        f,
        values=['VERSION'],
        exportselection=0,
        # On Mac this defaults to being way too wide!
        width=7 if utils.MAC else None,
    )
    wid['variant'].state(['readonly'])  # Prevent directly typing in values
    wid['variant'].bind('<<ComboboxSelected>>', set_item_version)
    wid['variant'].current(0)
    wid['variant'].grid(row=6, column=0, sticky=W)

    itemPropWin.init(hide_item_props)
Пример #31
0
    def __init__(
            self,
            tk,
            lst,
            has_none=True,
            has_def=True,
            has_snd_sample=False,
            none_desc=(('line', 'Do not add anything.'),),
            none_attrs: dict=utils.EmptyMapping,
            title='BEE2',
            desc='',
            readonly_desc='',
            callback: Callable[..., None]=None,
            callback_params=(),
            attributes=(),
    ):
        """Create a window object.

        Read from .selected_id to get the currently-chosen Item name, or None
        if the <none> Item is selected.
        Args:
        - tk: Must be a Toplevel window, either the tk() root or another
        window if needed.
        - lst: A list of Item objects, defining the visible items.
        - If has_none is True, a <none> item will be added to the beginning
          of the list.
        - If has_def is True, the 'Reset to Default' button will appear,
          which resets to the suggested item.
        - If has_snd_sample is True, a '>' button will appear next to names
          to play the associated audio sample for the item.
        - none_desc holds an optional description for the <none> Item,
          which can be used to describe what it results in.
        - title is the title of the selector window.
        - callback is a function to be called whenever the selected item
         changes.
        - callback_params is a list of additional values which will be
          passed to the callback function.
          The first arguement to the callback is always the selected item ID.
        - full_context controls if the short or long names are used for the
          context menu.
        - attributes is a list of AttrDef tuples.
          Each tuple should contain an ID, display text, and default value.
          If the values are True or False a check/cross will be displayed,
          otherwise they're a string.
        - desc is descriptive text to display on the window, and in the widget
          tooltip.
        - readonly_desc will be displayed on the widget tooltip when readonly.
        """
        self.noneItem = Item(
            'NONE',
            '',
            desc=none_desc,
            attributes=dict(none_attrs),
        )
        self.noneItem.icon = img.png('BEE2/none_96')

        # The textbox on the parent window.
        self.display = None  # type: tk_tools.ReadOnlyEntry

        # Variable associated with self.display.
        self.disp_label = StringVar()

        # The '...' button to open our window.
        self.disp_btn = None  # type: ttk.Button

        # ID of the currently chosen item
        self.chosen_id = None

        # Callback function, and positional arugments to pass
        if callback is not None:
            self.callback = callback
            self.callback_params = list(callback_params)
        else:
            self.callback = None
            self.callback_params = ()

        # Item object for the currently suggested item.
        self.suggested = None

        # Should we have the 'reset to default' button?
        self.has_def = has_def
        self.description = desc
        self.readonly_description = readonly_desc

        if has_none:
            self.item_list = [self.noneItem] + lst
        else:
            self.item_list = lst
        self.selected = self.item_list[0]  # type: Item
        self.orig_selected = self.selected
        self.parent = tk
        self._readonly = False

        self.win = Toplevel(tk)
        self.win.withdraw()
        self.win.title("BEE2 - " + title)
        self.win.transient(master=tk)

        # Allow resizing in X and Y.
        self.win.resizable(True, True)

        self.win.iconbitmap('../BEE2.ico')

        # Run our quit command when the exit button is pressed, or Escape
        # on the keyboard.
        self.win.protocol("WM_DELETE_WINDOW", self.exit)
        self.win.bind("<Escape>", self.exit)

        # Allow navigating with arrow keys.
        self.win.bind("<KeyPress>", self.key_navigate)

        # A map from group name -> header widget
        self.group_widgets = {}
        # A map from folded name -> display name
        self.group_names = {}
        self.grouped_items = defaultdict(list)
        # A list of folded group names in the display order.
        self.group_order = []

        # The maximum number of items that fits per row (set in flow_items)
        self.item_width = 1

        if desc:
            self.desc_label = ttk.Label(
                self.win,
                text=desc,
                justify=LEFT,
                anchor=W,
                width=5,  # Keep a small width, so this doesn't affect the
                # initial window size.
            )
            self.desc_label.grid(row=0, column=0, sticky='EW')

        # PanedWindow allows resizing the two areas independently.
        self.pane_win = PanedWindow(
            self.win,
            orient=HORIZONTAL,
            sashpad=2,  # Padding above/below panes
            sashwidth=3,  # Width of border
            sashrelief=RAISED,  # Raise the border between panes
        )
        self.pane_win.grid(row=1, column=0, sticky="NSEW")
        self.win.columnconfigure(0, weight=1)
        self.win.rowconfigure(1, weight=1)

        self.wid = {}
        shim = ttk.Frame(self.pane_win, relief="sunken")
        shim.rowconfigure(0, weight=1)
        shim.columnconfigure(0, weight=1)

        # We need to use a canvas to allow scrolling.
        self.wid_canvas = Canvas(shim, highlightthickness=0)
        self.wid_canvas.grid(row=0, column=0, sticky="NSEW")

        # Add another frame inside to place labels on.
        self.pal_frame = ttk.Frame(self.wid_canvas)
        self.wid_canvas.create_window(1, 1, window=self.pal_frame, anchor="nw")

        self.wid_scroll = tk_tools.HidingScroll(
            shim,
            orient=VERTICAL,
            command=self.wid_canvas.yview,
        )
        self.wid_scroll.grid(row=0, column=1, sticky="NS")
        self.wid_canvas['yscrollcommand'] = self.wid_scroll.set

        utils.add_mousewheel(self.wid_canvas, self.win)

        if utils.MAC:
            # Labelframe doesn't look good here on OSX
            self.sugg_lbl = ttk.Label(
                self.pal_frame,
                # Draw lines with box drawing characters
                text="\u250E\u2500Suggested\u2500\u2512"
            )
        else:
            self.sugg_lbl = ttk.LabelFrame(
                self.pal_frame,
                text="Suggested",
                labelanchor=N,
                height=50,
            )

        # Holds all the widgets which provide info for the current item.
        self.prop_frm = ttk.Frame(self.pane_win, borderwidth=4, relief='raised')
        self.prop_frm.columnconfigure(1, weight=1)

        # Border around the selected item icon.
        self.prop_icon_frm = ttk.Frame(
            self.prop_frm,
            borderwidth=4,
            relief='raised',
            width=ICON_SIZE,
            height=ICON_SIZE,
        )
        self.prop_icon_frm.grid(row=0, column=0, columnspan=4)

        self.prop_icon = ttk.Label(self.prop_icon_frm)
        self.prop_icon.img = img.png('BEE2/blank_96')
        self.prop_icon['image'] = self.prop_icon.img
        self.prop_icon.grid(row=0, column=0)

        name_frame = ttk.Frame(self.prop_frm)

        self.prop_name = ttk.Label(
            name_frame,
            text="Item",
            justify=CENTER,
            font=("Helvetica", 12, "bold"),
        )
        name_frame.grid(row=1, column=0, columnspan=4)
        name_frame.columnconfigure(0, weight=1)
        self.prop_name.grid(row=0, column=0)

        # For music items, add a '>' button to play sound samples
        if has_snd_sample and sound.initiallised:
            self.samp_button = samp_button = ttk.Button(
                name_frame,
                text=BTN_PLAY,
                width=1,
            )
            samp_button.grid(row=0, column=1)
            add_tooltip(
                samp_button,
                "Play a sample of this item.",
            )

            def set_samp_play():
                samp_button['text'] = BTN_PLAY

            def set_samp_stop():
                samp_button['text'] = BTN_STOP

            self.sampler = sound.SamplePlayer(
                stop_callback=set_samp_play,
                start_callback=set_samp_stop,
            )
            samp_button['command'] = self.sampler.play_sample
            utils.bind_leftclick(self.prop_icon, self.sampler.play_sample)
            samp_button.state(('disabled',))
        else:
            self.sampler = None

        self.prop_author = ttk.Label(self.prop_frm, text="Author")
        self.prop_author.grid(row=2, column=0, columnspan=4)

        self.prop_desc_frm = ttk.Frame(self.prop_frm, relief="sunken")
        self.prop_desc_frm.grid(row=4, column=0, columnspan=4, sticky="NSEW")
        self.prop_desc_frm.rowconfigure(0, weight=1)
        self.prop_desc_frm.columnconfigure(0, weight=1)
        self.prop_frm.rowconfigure(4, weight=1)

        self.prop_desc = tkRichText(
            self.prop_desc_frm,
            width=40,
            height=4,
            font="TkSmallCaptionFont",
        )
        self.prop_desc.grid(
            row=0,
            column=0,
            padx=(2, 0),
            pady=2,
            sticky='NSEW',
        )

        self.prop_scroll = tk_tools.HidingScroll(
            self.prop_desc_frm,
            orient=VERTICAL,
            command=self.prop_desc.yview,
        )
        self.prop_scroll.grid(
            row=0,
            column=1,
            sticky="NS",
            padx=(0, 2),
            pady=2,
        )
        self.prop_desc['yscrollcommand'] = self.prop_scroll.set

        ttk.Button(
            self.prop_frm,
            text="OK",
            command=self.save,
        ).grid(
            row=6,
            column=0,
            padx=(8, 8),
            )

        if self.has_def:
            self.prop_reset = ttk.Button(
                self.prop_frm,
                text="Reset to Default",
                command=self.sel_suggested,
            )
            self.prop_reset.grid(
                row=6,
                column=1,
                sticky='EW',
            )

        ttk.Button(
            self.prop_frm,
            text="Cancel",
            command=self.exit,
        ).grid(
            row=6,
            column=2,
            padx=(8, 8),
        )

        self.win.option_add('*tearOff', False)
        self.context_menu = Menu(self.win)

        self.norm_font = tk_font.nametofont('TkMenuFont')

        # Make a font for showing suggested items in the context menu
        self.sugg_font = self.norm_font.copy()
        self.sugg_font['weight'] = tk_font.BOLD

        # Make a font for previewing the suggested item
        self.mouseover_font = self.norm_font.copy()
        self.mouseover_font['slant'] = tk_font.ITALIC
        self.context_var = IntVar()

        # The headers for the context menu
        self.context_menus = {}

        # Sort alphabetically, prefering a sort key if present.
        self.item_list.sort(key=lambda it: it.sort_key or it.longName)

        for ind, item in enumerate(self.item_list):  # type: int, Item
            if item == self.noneItem:
                item.button = ttk.Button(
                    self.pal_frame,
                    image=item.icon,
                )
                item.context_lbl = '<None>'
            else:
                item.button = ttk.Button(
                    self.pal_frame,
                    text=item.shortName,
                    image=item.icon,
                    compound='top',
                )

            group_key = item.group.casefold()
            self.grouped_items[group_key].append(item)

            if group_key not in self.group_names:
                # If the item is groupless, use 'Other' for the header.
                self.group_names[group_key] = item.group or 'Other'

            if not item.group:
                # Ungrouped items appear directly in the menu.
                menu = self.context_menu
            else:
                try:
                    menu = self.context_menus[group_key]
                except KeyError:
                    self.context_menus[group_key] = menu = Menu(
                        self.context_menu,
                    )

            menu.add_radiobutton(
                label=item.context_lbl,
                command=functools.partial(self.sel_item_id, item.name),
                var=self.context_var,
                value=ind,
            )

            item.win = self.win
            utils.bind_leftclick(
                item.button,
                functools.partial(self.sel_item, item),
            )
            utils.bind_leftclick_double(
                item.button,
                self.save,
            )

        # Convert to a normal dictionary, after adding all items.
        self.grouped_items = dict(self.grouped_items)

        # Figure out the order for the groups - alphabetical.
        # Note - empty string should sort to the beginning!
        self.group_order[:] = sorted(self.grouped_items.keys())

        for index, (key, menu) in enumerate(
                sorted(self.context_menus.items(), key=itemgetter(0)),
                # We start with the ungrouped items, so increase the index
                # appropriately.
                start=len(self.grouped_items.get('', ()))):
            self.context_menu.add_cascade(
                menu=menu,
                label=self.group_names[key],
            )
            # Set a custom attribute to keep track of the menu's index.
            menu.index = index

        for group_key, text in self.group_names.items():
            self.group_widgets[group_key] = GroupHeader(
                self,
                text,
            )
            self.group_widgets[group_key].should_show = True

        self.flow_items(None)
        self.wid_canvas.bind("<Configure>", self.flow_items)

        self.pane_win.add(shim)
        self.pane_win.add(self.prop_frm)

        # Force a minimum size for the two parts
        self.pane_win.paneconfigure(shim, minsize=100, stretch='always')
        self.prop_frm.update_idletasks()  # Update reqwidth()
        self.pane_win.paneconfigure(
            self.prop_frm,
            minsize=200,
            stretch='never',
        )

        if attributes:
            attr_frame = ttk.Frame(self.prop_frm)
            attr_frame.grid(
                row=5,
                column=0,
                columnspan=3,
                sticky=EW,
            )

            self.attr = {}
            # Add in all the attribute labels
            for index, attr in enumerate(attributes):
                desc_label = ttk.Label(
                    attr_frame,
                    text=attr.desc,
                )
                self.attr[attr.id] = val_label = ttk.Label(
                    attr_frame,
                )
                val_label.default = attr.default
                val_label.type = attr.type
                if attr.type is AttrTypes.BOOL:
                    # It's a tick/cross label
                    val_label['image'] = (
                        ICON_CHECK
                        if attr.default else
                        ICON_CROSS,
                    )
                elif attr.type is AttrTypes.COLOR:
                    # A small colour swatch.
                    val_label.configure(
                        relief=RAISED,
                    )
                    # Show the color value when hovered.
                    add_tooltip(val_label)

                # Position in a 2-wide grid
                desc_label.grid(
                    row=index // 2,
                    column=(index % 2) * 2,
                    sticky=E,
                )
                val_label.grid(
                    row=index // 2,
                    column=(index % 2) * 2 + 1,
                    sticky=W,
                )
        else:
            self.attr = None
Пример #32
0
def init() -> None:
    """Initialise all widgets in the given window."""
    for cat, btn_text in [
        ('back_', _('Restore:')),
        ('game_', _('Backup:')),
    ]:
        UI[cat + 'frame'] = frame = ttk.Frame(window, )
        UI[cat + 'title_frame'] = title_frame = ttk.Frame(frame, )
        title_frame.grid(row=0, column=0, sticky='EW')
        UI[cat + 'title'] = ttk.Label(
            title_frame,
            font='TkHeadingFont',
        )
        UI[cat + 'title'].grid(row=0, column=0)
        title_frame.rowconfigure(0, weight=1)
        title_frame.columnconfigure(0, weight=1)

        UI[cat + 'details'] = CheckDetails(
            frame,
            headers=HEADERS,
        )
        UI[cat + 'details'].grid(row=1, column=0, sticky='NSEW')
        frame.rowconfigure(1, weight=1)
        frame.columnconfigure(0, weight=1)

        button_frame = ttk.Frame(frame, )
        button_frame.grid(column=0, row=2)
        ttk.Label(button_frame, text=btn_text).grid(row=0, column=0)
        UI[cat + 'btn_all'] = ttk.Button(
            button_frame,
            text='All',
            width=3,
        )
        UI[cat + 'btn_sel'] = ttk.Button(
            button_frame,
            text=_('Checked'),
            width=8,
        )
        UI[cat + 'btn_all'].grid(row=0, column=1)
        UI[cat + 'btn_sel'].grid(row=0, column=2)

        UI[cat + 'btn_del'] = ttk.Button(
            button_frame,
            text=_('Delete Checked'),
            width=14,
        )
        UI[cat + 'btn_del'].grid(row=1, column=0, columnspan=3)

        utils.add_mousewheel(
            UI[cat + 'details'].wid_canvas,
            UI[cat + 'frame'],
        )

    UI['game_refresh'] = ttk.Button(
        UI['game_title_frame'],
        image=img.png('icons/tool_sub'),
        command=ui_refresh_game,
    )
    UI['game_refresh'].grid(row=0, column=1, sticky='E')
    add_tooltip(
        UI['game_refresh'],
        "Reload the map list.",
    )

    UI['game_title']['textvariable'] = game_name
    UI['back_title']['textvariable'] = backup_name

    UI['game_btn_all']['command'] = ui_backup_all
    UI['game_btn_sel']['command'] = ui_backup_sel
    UI['game_btn_del']['command'] = ui_delete_game

    UI['back_btn_all']['command'] = ui_restore_all
    UI['back_btn_sel']['command'] = ui_restore_sel
    UI['back_btn_del']['command'] = ui_delete_backup

    UI['back_frame'].grid(row=1, column=0, sticky='NSEW')
    ttk.Separator(orient=tk.VERTICAL).grid(
        row=1,
        column=1,
        sticky='NS',
        padx=5,
    )
    UI['game_frame'].grid(row=1, column=2, sticky='NSEW')

    window.rowconfigure(1, weight=1)
    window.columnconfigure(0, weight=1)
    window.columnconfigure(2, weight=1)
Пример #33
0
    def __init__(
            self,
            tk,
            lst,
            has_none=True,
            has_def=True,
            none_desc=(('line', 'Do not add anything.'),),
            title='BEE2',
            callback=_NO_OP,
            callback_params=(),
            attributes=(),
            ):
        """Create a window object.

        Read from .selected_id to get the currently-chosen Item name, or None
        if the <none> Item is selected.
        Args:
        - tk: Must be a Toplevel window, either the tk() root or another
        window if needed.
        - lst: A list of Item objects, defining the visible items.
        - If has_none is True, a <none> item will be added to the beginning
          of the list.
        - If has_def is True, the 'Reset to Default' button will appear,
          which resets to the suggested item.
        - none_desc holds an optional description for the <none> Item,
          which can be used to describe what it results in.
        - title is the title of the selector window.
        - callback is a function to be called whenever the selected item
         changes.
        - callback_params is a list of additional values which will be
          passed to the callback function.
          The first arguement to the callback is always the selected item ID.
        - full_context controls if the short or long names are used for the
          context menu.
        - attributes is a list of AttrDef tuples.
          Each tuple should contain an ID, display text, and default value.
          If the values are True or False a check/cross will be displayed,
          otherwise they're a string.
        """
        self.noneItem = Item('NONE', '', desc=none_desc)
        self.noneItem.icon = img.png('BEE2/none_96')
        self.disp_label = StringVar()
        self.display = None
        self.disp_btn = None
        self.chosen_id = None
        self.callback = callback
        self.callback_params = callback_params
        self.suggested = None
        self.has_def = has_def

        if has_none:
            self.item_list = [self.noneItem] + lst
        else:
            self.item_list = lst
        self.selected = self.item_list[0]
        self.orig_selected = self.selected
        self.parent = tk
        self._readonly = False

        self.win = Toplevel(tk)
        self.win.withdraw()
        self.win.title("BEE2 - " + title)
        self.win.transient(master=tk)
        self.win.resizable(True, True)
        self.win.iconbitmap('../BEE2.ico')
        self.win.protocol("WM_DELETE_WINDOW", self.exit)
        self.win.bind("<Escape>", self.exit)

        self.win.columnconfigure(0, weight=1)
        self.win.rowconfigure(0, weight=1)

        # PanedWindow allows resizing the two areas independently.
        self.pane_win = PanedWindow(
            self.win,
            orient=HORIZONTAL,
            sashpad=2,  # Padding above/below panes
            sashwidth=3,  # Width of border
            sashrelief=RAISED,  # Raise the border between panes
        )
        self.pane_win.grid(row=0, column=0, sticky="NSEW")
        self.win.columnconfigure(0, weight=1)
        self.win.rowconfigure(0, weight=1)

        self.wid = {}
        shim = ttk.Frame(self.pane_win, relief="sunken")
        shim.rowconfigure(0, weight=1)
        shim.columnconfigure(0, weight=1)

        # We need to use a canvas to allow scrolling.
        self.wid_canvas = Canvas(shim, highlightthickness=0)
        self.wid_canvas.grid(row=0, column=0, sticky="NSEW")

        # Add another frame inside to place labels on.
        self.pal_frame = ttk.Frame(self.wid_canvas)
        self.wid_canvas.create_window(1, 1, window=self.pal_frame, anchor="nw")

        self.wid_scroll = ttk.Scrollbar(
            shim,
            orient=VERTICAL,
            command=self.wid_canvas.yview,
        )
        self.wid_scroll.grid(row=0, column=1, sticky="NS")
        self.wid_canvas['yscrollcommand'] = self.wid_scroll.set

        if utils.MAC:
            # Labelframe doesn't look good here on OSX
            self.sugg_lbl = ttk.Label(
                self.pal_frame,
                # Draw lines with box drawing characters
                text="\u250E\u2500Suggested\u2500\u2512"
            )
        else:
            self.sugg_lbl = ttk.LabelFrame(
                self.pal_frame,
                text="Suggested",
                labelanchor=N,
                height=50,
            )

        # Holds all the widgets which provide info for the current item.
        self.prop_frm = ttk.Frame(self.pane_win, borderwidth=4, relief='raised')
        self.prop_frm.columnconfigure(1, weight=1)

        # Border around the selected item icon.
        self.prop_icon_frm = ttk.Frame(
            self.prop_frm,
            borderwidth=4,
            relief='raised',
            width=ICON_SIZE,
            height=ICON_SIZE,
            )
        self.prop_icon_frm.grid(row=0, column=0, columnspan=4)

        self.prop_icon = ttk.Label(self.prop_icon_frm)
        self.prop_icon.img = img.png('BEE2/blank_96')
        self.prop_icon['image'] = self.prop_icon.img
        self.prop_icon.grid(row=0, column=0)

        self.prop_name = ttk.Label(
            self.prop_frm,
            text="Item",
            justify=CENTER,
            font=("Helvetica", 12, "bold"),
            )
        self.prop_name.grid(row=1, column=0, columnspan=4)
        self.prop_author = ttk.Label(self.prop_frm, text="Author")
        self.prop_author.grid(row=2, column=0, columnspan=4)

        self.prop_desc_frm = ttk.Frame(self.prop_frm, relief="sunken")
        self.prop_desc_frm.grid(row=4, column=0, columnspan=4, sticky="NSEW")
        self.prop_desc_frm.rowconfigure(0, weight=1)
        self.prop_desc_frm.columnconfigure(0, weight=1)
        self.prop_frm.rowconfigure(4, weight=1)

        self.prop_desc = tkRichText(
            self.prop_desc_frm,
            width=40,
            height=4,
            font="TkSmallCaptionFont",
            )
        self.prop_desc.grid(
            row=0,
            column=0,
            padx=(2, 0),
            pady=2,
            sticky='NSEW',
            )

        self.prop_scroll = ttk.Scrollbar(
            self.prop_desc_frm,
            orient=VERTICAL,
            command=self.prop_desc.yview,
            )
        self.prop_scroll.grid(
            row=0,
            column=1,
            sticky="NS",
            padx=(0, 2),
            pady=2,
        )
        self.prop_desc['yscrollcommand'] = self.prop_scroll.set

        ttk.Button(
            self.prop_frm,
            text="OK",
            command=self.save,
            ).grid(
                row=6,
                column=0,
                padx=(8, 8),
                )

        if self.has_def:
            self.prop_reset = ttk.Button(
                self.prop_frm,
                text="Reset to Default",
                command=self.sel_suggested,
                )
            self.prop_reset.grid(
                row=6,
                column=1,
                sticky='EW',
                )

        ttk.Button(
            self.prop_frm,
            text="Cancel",
            command=self.exit,
            ).grid(
                row=6,
                column=2,
                padx=(8, 8),
                )

        self.win.option_add('*tearOff', False)
        self.context_menu = Menu(self.win)

        self.norm_font = font.nametofont('TkMenuFont')

        # Make a font for showing suggested items in the context menu
        self.sugg_font = self.norm_font.copy()
        self.sugg_font['weight'] = font.BOLD

        # Make a font for previewing the suggested item
        self.mouseover_font = self.norm_font.copy()
        self.mouseover_font['slant'] = font.ITALIC
        self.context_var = IntVar()

        # Re-order items appropriately.
        #
        self.item_list.sort(
            # Alphabetical order
            key=lambda it: it.longName
        )
        self.item_list.sort(
            # Sort by group name
            key=lambda it: it.group.casefold() if it.group else ''
        )
        self.item_list.sort(
            # Make non-grouped items go first
            key=lambda it: 2 if it.group else 1
        )

        for ind, item in enumerate(self.item_list):
            if item == self.noneItem:
                item.button = ttk.Button(
                    self.pal_frame,
                    image=item.icon,
                    )
                item.context_lbl = '<None>'
            else:
                item.button = ttk.Button(
                    self.pal_frame,
                    text=item.shortName,
                    image=item.icon,
                    compound='top',
                    )
            self.context_menu.add_radiobutton(
                label=item.context_lbl,
                command=functools.partial(self.sel_item_id, item.name),
                var=self.context_var,
                value=ind,
                )

            item.win = self.win
            utils.bind_leftclick(
                item.button,
                functools.partial(self.sel_item, item),
            )
            utils.bind_leftclick_double(
                item.button,
                self.save,
            )
        self.flow_items(None)
        self.wid_canvas.bind("<Configure>", self.flow_items)

        self.pane_win.add(shim)
        self.pane_win.add(self.prop_frm)

        # Force a minimum size for the two parts
        self.pane_win.paneconfigure(shim, minsize=100, stretch='always')
        self.prop_frm.update_idletasks()  # Update reqwidth()
        self.pane_win.paneconfigure(
            self.prop_frm,
            minsize=200,
            stretch='never',
        )

        if attributes:
            attr_frame = ttk.Frame(self.prop_frm)
            attr_frame.grid(
                row=5,
                column=0,
                columnspan=3,
                sticky=EW,
            )

            self.attr = {}
            # Add in all the attribute labels
            for index, (at_id, desc, value) in enumerate(attributes):
                desc_label = ttk.Label(
                    attr_frame,
                    text=desc,
                )
                self.attr[at_id] = val_label = ttk.Label(
                    attr_frame,
                )
                val_label.default = value
                if isinstance(value, bool):
                    # It's a tick/cross label
                    val_label['image'] = (
                        ICON_CHECK
                        if value else
                        ICON_CROSS,
                    )
                # Position in a 2-wide grid
                desc_label.grid(
                    row=index // 2,
                    column=(index % 2)*2,
                    sticky=E,
                )
                val_label.grid(
                    row=index // 2,
                    column=(index % 2)*2 + 1,
                    sticky=W,
                )
        else:
            self.attr = None
Пример #34
0
    def __init__(
            self,
            tk,
            lst,
            has_none=True,
            has_def=True,
            none_desc=(('line', 'Do not add anything.'),),
            title='BEE2',
            callback=_NO_OP,
            callback_params=(),
            ):
        """Create a window object.

        Read from .selected_id to get the currently-chosen Item name, or None
        if the <none> Item is selected.
        Args:
        - tk: Must be a Toplevel window, either the tk() root or another
        window if needed.
        - lst: A list of Item objects, defining the visible items.
        - If has_none is True, a <none> item will be added to the beginning
          of the list.
        - If has_def is True, the 'Reset to Default' button will appear,
          which resets to the suggested item.
        - none_desc holds an optional description for the <none> Item,
          which can be used to describe what it results in.
        - title is the title of the selector window.
        - callback is a function to be called whenever the selected item
         changes.
        - callback_params is a list of additional values which will be
          passed to the callback function.
          The first arguement to the callback is always the selected item ID.
        - full_context controls if the short or long names are used for the
          context menu.
        """
        self.noneItem = Item('NONE', '', desc=none_desc)
        self.noneItem.icon = img.png('BEE2/none_96')
        self.disp_label = StringVar()
        self.display = None
        self.disp_btn = None
        self.chosen_id = None
        self.callback = callback
        self.callback_params = callback_params
        self.suggested = None
        self.has_def = has_def

        if has_none:
            self.item_list = [self.noneItem] + lst
        else:
            self.item_list = lst
        self.selected = self.item_list[0]
        self.orig_selected = self.selected
        self.parent = tk
        self._readonly = False

        self.win = Toplevel(tk)
        self.win.withdraw()
        self.win.title("BEE2 - " + title)
        self.win.transient(master=tk)
        self.win.resizable(True, True)
        self.win.iconbitmap('../BEE2.ico')
        self.win.protocol("WM_DELETE_WINDOW", self.exit)
        self.win.bind("<Escape>", self.exit)

        # PanedWindow allows resizing the two areas independently.
        self.pane_win = ttk.Panedwindow(self.win, orient=HORIZONTAL)
        self.pane_win.grid(row=0, column=0, sticky="NSEW")

        self.wid = {}
        shim = ttk.Frame(self.pane_win, relief="sunken")
        self.win.rowconfigure(0, weight=1)
        self.win.columnconfigure(0, weight=1)
        shim.rowconfigure(0, weight=1)
        shim.columnconfigure(0, weight=1)

        # We need to use a canvas to allow scrolling.
        self.wid_canvas = Canvas(shim, highlightthickness=0)
        self.wid_canvas.grid(row=0, column=0, sticky="NSEW")

        # Add another frame inside to place labels on.
        self.pal_frame = ttk.Frame(self.wid_canvas)
        self.wid_canvas.create_window(1, 1, window=self.pal_frame, anchor="nw")

        self.wid_scroll = ttk.Scrollbar(
            shim,
            orient=VERTICAL,
            command=self.wid_canvas.yview,
        )
        self.wid_scroll.grid(row=0, column=1, sticky="NS")
        self.wid_canvas['yscrollcommand'] = self.wid_scroll.set

        self.sugg_lbl = ttk.LabelFrame(
            self.pal_frame,
            text="Suggested",
            labelanchor=N,
            height=50,
        )

        # Holds all the widgets which provide info for the current item.
        self.prop_frm = ttk.Frame(self.pane_win, borderwidth=4, relief='raised')
        self.prop_frm.columnconfigure(1, weight=1)

        # Border around the selected item icon.
        self.prop_icon_frm = ttk.Frame(
            self.prop_frm,
            borderwidth=4,
            relief='raised',
            width=ICON_SIZE,
            height=ICON_SIZE,
            )
        self.prop_icon_frm.grid(row=0, column=0, columnspan=4)

        self.prop_icon = ttk.Label(self.prop_icon_frm)
        self.prop_icon.img = img.png('BEE2/blank_96')
        self.prop_icon['image'] = self.prop_icon.img
        self.prop_icon.grid(row=0, column=0)

        self.prop_name = ttk.Label(
            self.prop_frm,
            text="Item",
            justify=CENTER,
            font=("Helvetica", 12, "bold"),
            )
        self.prop_name.grid(row=1, column=0, columnspan=4)
        self.prop_author = ttk.Label(self.prop_frm, text="Author")
        self.prop_author.grid(row=2, column=0, columnspan=4)

        self.prop_desc_frm = ttk.Frame(self.prop_frm, relief="sunken")
        self.prop_desc_frm.grid(row=4, column=0, columnspan=4, sticky="NSEW")
        self.prop_desc_frm.rowconfigure(0, weight=1)
        self.prop_desc_frm.columnconfigure(0, weight=1)
        self.prop_frm.rowconfigure(4, weight=1)

        self.prop_desc = tkRichText(
            self.prop_desc_frm,
            width=40,
            height=16,
            font="TkSmallCaptionFont",
            )
        self.prop_desc.grid(
            row=0,
            column=0,
            padx=(2, 0),
            pady=2,
            sticky='NSEW',
            )

        self.prop_scroll = ttk.Scrollbar(
            self.prop_desc_frm,
            orient=VERTICAL,
            command=self.prop_desc.yview,
            )
        self.prop_scroll.grid(
            row=0,
            column=1,
            sticky="NS",
            padx=(0, 2),
            pady=2,
        )
        self.prop_desc['yscrollcommand'] = self.prop_scroll.set

        ttk.Button(
            self.prop_frm,
            text="OK",
            command=self.save,
            ).grid(
                row=5,
                column=0,
                padx=(8, 8),
                )

        if self.has_def:
            self.prop_reset = ttk.Button(
                self.prop_frm,
                text="Reset to Default",
                command=self.sel_suggested,
                )
            self.prop_reset.grid(
                row=5,
                column=1,
                sticky='EW',
                )

        ttk.Button(
            self.prop_frm,
            text="Cancel",
            command=self.exit,
            ).grid(
                row=5,
                column=2,
                padx=(8, 8),
                )

        self.win.option_add('*tearOff', False)
        self.context_menu = Menu(self.win)

        self.norm_font = font.nametofont('TkMenuFont')

        # Make a font for showing suggested items in the context menu
        self.sugg_font = self.norm_font.copy()
        self.sugg_font['weight'] = font.BOLD

        # Make a font for previewing the suggested item
        self.mouseover_font = self.norm_font.copy()
        self.mouseover_font['slant'] = font.ITALIC
        self.context_var = IntVar()

        # Re-order items appropriately.
        #
        self.item_list.sort(
            # Alphabetical order
            key=lambda it: it.longName
        )
        self.item_list.sort(
            # Sort by group name
            key=lambda it: it.group.casefold() if it.group else ''
        )
        self.item_list.sort(
            # Make non-grouped items go first
            key=lambda it: 2 if it.group else 1
        )

        for ind, item in enumerate(self.item_list):
            if item == self.noneItem:
                item.button = ttk.Button(
                    self.pal_frame,
                    image=item.icon,
                    )
                item.context_lbl = '<None>'
            else:
                item.button = ttk.Button(
                    self.pal_frame,
                    text=item.shortName,
                    image=item.icon,
                    compound='top',
                    )
            self.context_menu.add_radiobutton(
                label=item.context_lbl,
                command=functools.partial(self.sel_item_id, item.name),
                var=self.context_var,
                value=ind,
                )

            item.win = self.win
            item.button.bind(
                "<Button-1>",
                functools.partial(self.sel_item, item),
            )
            item.button.bind("<Double-Button-1>", self.save)
        self.flow_items(None)
        self.wid_canvas.bind("<Configure>", self.flow_items)

        self.pane_win.add(shim, weight=1)
        self.pane_win.add(self.prop_frm)
Пример #35
0
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Style Properties',
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_stylevar'),
        tool_col=3,
    )

    UI['style_can'] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        window,
        orient=VERTICAL,
        command=UI['style_can'].yview,
        )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set

    utils.add_mousewheel(UI['style_can'], window)

    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text="All:")
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text="Selected Style:")
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
        ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text="Other Styles:")
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text='No Options!',
        font='TkMenuFont',
        justify='center',
        )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text='None!',
        font='TkMenuFont',
        justify='center',
        )

    for pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = IntVar(
            value=GEN_OPTS.get_bool('StyleVar', var.id, var.default)
        )
        checkbox_special[var.id] = ttk.Checkbutton(
            frame_all,
            variable=tk_vars[var.id],
            text=var.name,
            command=functools.partial(set_stylevar, var.id)
            )
        checkbox_special[var.id].grid(row=pos, column=0, sticky="W", padx=3)

        tooltip.add_tooltip(
            checkbox_special[var.id],
            make_desc(var, is_hardcoded=True),
        )

    for var in VAR_LIST:
        tk_vars[var.id] = IntVar(value=var.enabled)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            'command': functools.partial(set_stylevar, var.id)
            }
        checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
        checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
        desc = make_desc(var)
        tooltip.add_tooltip(
            checkbox_chosen[var.id],
            desc,
        )
        tooltip.add_tooltip(
            checkbox_other[var.id],
            desc,
        )

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
    )

    if utils.USE_SIZEGRIP:
        ttk.Sizegrip(
            window,
            cursor=utils.CURSORS['stretch_vert'],
        ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)
Пример #36
0
"""
from tkinter import *  # ui library
from tkinter import font
from tkinter import ttk  # themed ui components that match the OS
import functools
import math

import img as png  # png library for TKinter
from richTextBox import tkRichText
import utils

ICON_SIZE = 96  # Size of the selector win icons
ITEM_WIDTH = ICON_SIZE+16
ITEM_HEIGHT = ICON_SIZE+51

err_icon = png.png('BEE2/error_96', resize_to=96)


def _NO_OP(*args):
    """The default callback, triggered whenever the chosen item is changed."""
    pass


class Item:
    """An item on the panel.

    - name: The item ID, used to distinguish it from others.
    - longName: The full item name. This can be very long. If not set,
      this will be the same as the short name.
    - shortName: A shortened version of the full name. This should be <= 20
      characters.
Пример #37
0
import img
import utils
import tk_tools

LOGGER = utils.getLogger(__name__)

voice_item = None

UI = {}

TABS = {}

QUOTE_FONT = font.nametofont('TkHeadingFont').copy()
QUOTE_FONT['weight'] = 'bold'

SP_IMG = img.png('icons/quote_sp')
COOP_IMG = img.png('icons/quote_coop')

# Friendly names given to certain response channels.
RESPONSE_NAMES = {
    'death_goo': 'Death - Toxic Goo',
    'death_turret': 'Death - Turrets',
    'death_crush': 'Death - Crusher',
    'death_laserfield': 'Death - LaserField',
}

config = config_mid = config_resp = None # type: ConfigFile


class TabTypes(Enum):
    NORM = 0
Пример #38
0
def make_pane(tool_frame):
    """Create the compiler options pane.

    """
    global window
    window = SubPane.SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Compile Options',
        name='compiler',
        resize_x=True,
        resize_y=False,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_compiler'),
        tool_col=4,
    )
    window.columnconfigure(0, weight=1)

    thumb_frame = ttk.LabelFrame(
        window,
        text='Thumbnail',
        labelanchor=N,
    )
    thumb_frame.grid(row=0, column=0, sticky=EW)
    thumb_frame.columnconfigure(0, weight=1)

    UI['thumb_auto'] = ttk.Radiobutton(
        thumb_frame,
        text='Auto',
        value='AUTO',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_peti'] = ttk.Radiobutton(
        thumb_frame,
        text='PeTI',
        value='PETI',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_custom'] = ttk.Radiobutton(
        thumb_frame,
        text='Custom:',
        value='CUST',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_label'] = ttk.Label(
        thumb_frame,
        anchor=CENTER,
        cursor=utils.CURSORS['link'],
    )
    UI['thumb_label'].bind(
        utils.EVENTS['LEFT'],
        find_screenshot,
    )

    UI['thumb_cleanup'] = ttk.Checkbutton(
        thumb_frame,
        text='Cleanup old screenshots',
        variable=cleanup_screenshot,
        command=set_screenshot_cleanup,
    )

    UI['thumb_auto'].grid(row=0, column=0, sticky='W')
    UI['thumb_peti'].grid(row=0, column=1, sticky='W')
    UI['thumb_custom'].grid(row=1, column=0, columnspan=2, sticky='NEW')
    UI['thumb_cleanup'].grid(row=3, columnspan=2, sticky='W')
    add_tooltip(
        UI['thumb_auto'],
        "Override the map image to use a screenshot automatically taken"
        "from the beginning of a chamber. Press F5 to take a new "
        "screenshot. If the map has not been previewed recently "
        "(within the last few hours), the default PeTI screenshot "
        "will be used instead."
    )
    add_tooltip(
        UI['thumb_peti'],
        "Use the normal editor view for the map preview image."
    )
    custom_tooltip = (
        "Use a custom image for the map preview image. Click the "
        "screenshot to select.\n"
        "Images will be converted to JPEGs if needed."
    )
    add_tooltip(
        UI['thumb_custom'],
        custom_tooltip,
    )

    add_tooltip(
        UI['thumb_label'],
        custom_tooltip
    )

    add_tooltip(
        UI['thumb_cleanup'],
        'Automatically delete unused Automatic screenshots. '
        'Disable if you want to keep things in "portal2/screenshots". '
    )

    if chosen_thumb.get() == 'CUST':
        # Show this if the user has set it before
        UI['thumb_label'].grid(row=2, column=0, columnspan=2, sticky='EW')
    set_screenshot()  # Load the last saved screenshot

    vrad_frame = ttk.LabelFrame(
        window,
        text='Lighting:',
        labelanchor=N,
    )
    vrad_frame.grid(row=1, column=0, sticky=EW)

    UI['light_fast'] = ttk.Radiobutton(
        vrad_frame,
        text='Fast',
        value=0,
        variable=vrad_light_type,
        command=set_vrad_type,
    )
    UI['light_fast'].grid(row=0, column=0)
    UI['light_full'] = ttk.Radiobutton(
        vrad_frame,
        text='Full',
        value=1,
        variable=vrad_light_type,
        command=set_vrad_type,
    )
    UI['light_full'].grid(row=0, column=1)

    add_tooltip(
        UI['light_fast'],
        "Compile with lower-quality, fast lighting. This speeds "
        "up compile times, but does not appear as good. Some "
        "shadows may appear wrong.\n"
        "When publishing, this is ignored."
    )
    add_tooltip(
        UI['light_full'],
        "Compile with high-quality lighting. This looks correct, "
        "but takes longer to compute. Use if you're arranging lights."
        "When publishing, this is always used."
    )

    elev_frame = ttk.LabelFrame(
        window,
        text='Spawn at:',
        labelanchor=N,
    )

    elev_frame.grid(row=2, column=0, sticky=EW)
    elev_frame.columnconfigure(0, weight=1)
    elev_frame.columnconfigure(1, weight=1)

    UI['elev_preview'] = ttk.Radiobutton(
        elev_frame,
        text='Entry Door',
        value=0,
        variable=start_in_elev,
        command=set_elev_type,
    )

    UI['elev_elevator'] = ttk.Radiobutton(
        elev_frame,
        text='Elevator',
        value=1,
        variable=start_in_elev,
        command=set_elev_type,
    )

    UI['elev_preview'].grid(row=0, column=0, sticky=W)
    UI['elev_elevator'].grid(row=0, column=1, sticky=W)

    add_tooltip(
        UI['elev_elevator'],
        "When previewing in SP, spawn inside the entry elevator. "
        "This also disables the map restarts when you reach the "
        "exit door. Use this to examine the entry and exit corridors."
    )
    add_tooltip(
        UI['elev_preview'],
        "When previewing in SP, spawn just before the entry door. "
        "When you reach the exit door, the map will restart."
    )

    corr_frame = ttk.LabelFrame(
        window,
        text='Corridor:',
        labelanchor=N,
    )
    corr_frame.grid(row=3, column=0, sticky=EW)
    corr_frame.columnconfigure(0, weight=1)
    corr_frame.columnconfigure(1, weight=1)

    UI['corr_sp_entry'] = make_corr_combo(
        corr_frame,
        'sp_entry',
        width=9,
    )

    UI['corr_sp_exit'] = make_corr_combo(
        corr_frame,
        'sp_exit',
        width=9,
    )

    UI['corr_coop'] = make_corr_combo(
        corr_frame,
        'coop',
        width=9,
    )

    UI['corr_sp_entry'].grid(row=1, column=0, sticky=EW)
    UI['corr_sp_exit'].grid(row=1, column=1, sticky=EW)
    UI['corr_coop'].grid(row=2, column=1, sticky=EW)
    ttk.Label(
        corr_frame,
        text='SP Entry:',
        anchor=CENTER,
    ).grid(row=0, column=0, sticky=EW)
    ttk.Label(
        corr_frame,
        text='SP Exit:',
        anchor=CENTER,
    ).grid(row=0, column=1, sticky=EW)
    ttk.Label(
        corr_frame,
        text='Coop:',
        anchor=CENTER,
    ).grid(row=2, column=0, sticky=EW)

    model_frame = ttk.LabelFrame(
        window,
        text='Player Model (SP):',
        labelanchor=N,
    )
    model_frame.grid(row=4, column=0, sticky=EW)
    UI['player_mdl'] = ttk.Combobox(
        model_frame,
        exportselection=0,
        textvariable=player_model_var,
        values=PLAYER_MODEL_ORDER,
        width=20,
    )
    # Users can only use the dropdown
    UI['player_mdl'].state(['readonly'])
    UI['player_mdl'].grid(row=0, column=0, sticky=EW)

    UI['player_mdl'].bind('<<ComboboxSelected>>', set_model)
    model_frame.columnconfigure(0, weight=1)

    count_frame = ttk.LabelFrame(
        window,
        text='Last Compile:',
        labelanchor=N,
    )

    count_frame.grid(row=5, column=0, sticky=EW)
    count_frame.columnconfigure(0, weight=1)
    count_frame.columnconfigure(2, weight=1)

    ttk.Label(
        count_frame,
        text='Entity',
        anchor=N,
    ).grid(row=0, column=0, columnspan=3, sticky=EW)

    UI['count_ent'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_ENTS,
        variable=count_ents,
        length=120,
    )
    UI['count_ent'].grid(
        row=1,
        column=0,
        columnspan=3,
        sticky=EW,
        padx=5,
    )

    ttk.Label(
        count_frame,
        text='Overlay',
        anchor=CENTER,
    ).grid(row=2, column=0, sticky=EW)
    UI['count_over'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_OVERLAY,
        variable=count_overlay,
        length=50,
    )
    UI['count_over'].grid(row=3, column=0, sticky=EW, padx=5)

    UI['refresh_counts'] = SubPane.make_tool_button(
        count_frame,
        png.png('icons/tool_sub', resize_to=16),
        refresh_counts,
    )
    UI['refresh_counts'].grid(row=3, column=1)

    ttk.Label(
        count_frame,
        text='Brush',
        anchor=CENTER,
    ).grid(row=2, column=2, sticky=EW)
    UI['count_brush'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_BRUSH,
        variable=count_brush,
        length=50,
    )
    UI['count_brush'].grid(row=3, column=2, sticky=EW, padx=5)

    UI['view_logs'] = ttk.Button(
        count_frame,
        text='View Logs',
    )
    UI['view_logs'].grid(row=4, column=0, columnspan=3, sticky=EW)

    refresh_counts(reload=False)
Пример #39
0
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title="Style Properties",
        name="style",
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png("icons/win_stylevar"),
        tool_col=3,
    )

    UI["style_can"] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI["style_can"].grid(sticky="NSEW")
    window.rowconfigure(0, weight=1)

    UI["style_scroll"] = ttk.Scrollbar(window, orient=VERTICAL, command=UI["style_can"].yview)
    UI["style_scroll"].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI["style_can"]["yscrollcommand"] = UI["style_scroll"].set
    canvas_frame = ttk.Frame(UI["style_can"])

    frame_all = ttk.Labelframe(canvas_frame, text="All:")
    frame_all.grid(row=0, sticky="EW")

    frm_chosen = ttk.Labelframe(canvas_frame, text="Selected Style:")
    frm_chosen.grid(row=1, sticky="EW")

    ttk.Separator(canvas_frame, orient=HORIZONTAL).grid(row=2, sticky="EW", pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text="Other Styles:")
    frm_other.grid(row=3, sticky="EW")

    UI["stylevar_chosen_none"] = ttk.Label(frm_chosen, text="No Options!", font="TkMenuFont", justify="center")
    UI["stylevar_other_none"] = ttk.Label(frm_other, text="None!", font="TkMenuFont", justify="center")

    for pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = IntVar(value=GEN_OPTS.get_bool("StyleVar", var.id, var.enabled))
        checkbox_special[var.id] = ttk.Checkbutton(
            frame_all, variable=tk_vars[var.id], text=var.name, command=functools.partial(set_stylevar, var.id)
        )
        checkbox_special[var.id].grid(row=pos, column=0, sticky="W", padx=3)

        if var.desc:
            tooltip.add_tooltip(checkbox_special[var.id], var.desc)

    for var in var_list:
        tk_vars[var.id] = IntVar(value=var.default)
        args = {"variable": tk_vars[var.id], "text": var.name, "command": functools.partial(set_stylevar, var.id)}
        checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
        checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
        if var.desc:
            tooltip.add_tooltip(checkbox_chosen[var.id], var.desc)
            tooltip.add_tooltip(checkbox_other[var.id], var.desc)

    UI["style_can"].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI["style_can"].update_idletasks()
    UI["style_can"].config(scrollregion=UI["style_can"].bbox(ALL), width=canvas_frame.winfo_reqwidth())
    ttk.Sizegrip(window, cursor=utils.CURSORS["stretch_vert"]).grid(row=1, column=0)

    UI["style_can"].bind("<Configure>", flow_stylevar)

    # Scroll globally even if canvas is not selected.
    if utils.WIN:
        window.bind("<MouseWheel>", lambda e: scroll(int(-1 * (e.delta / 120))))
    elif utils.MAC:
        window.bind("<Button-4>", lambda e: scroll(1))
        window.bind("<Button-5>", lambda e: scroll(-1))
Пример #40
0
    def __init__(self, *args):
        super().__init__(*args)

        self.is_compact = True

        font = Font(
            family='Times',  # Generic special case
            size=-18,  # negative = in pixels
            weight='bold',
        )

        # Must be done late, so we know TK is initialised.
        import img

        logo_img = img.png('BEE2/splash_logo')

        self.lrg_canvas = tk.Canvas(self.win)
        self.sml_canvas = tk.Canvas(
            self.win,
            background='#009678',  # 0, 150, 120
        )

        sml_width = int(min(self.win.winfo_screenwidth() * 0.5, 400))
        sml_height = int(min(self.win.winfo_screenheight() * 0.5, 175))

        self.lrg_canvas.create_image(
            10, 10,
            anchor='nw',
            image=logo_img,
        )

        self.sml_canvas.create_text(
            sml_width / 2, 40,
            anchor='n',
            text=self.title_text,
            fill='white',
            font=font,
        )
        self.sml_canvas.create_text(
            sml_width / 2, 60,
            anchor='n',
            text=TRANSLATION['version'],
            fill='white',
            font=font,
        )

        text1 = self.lrg_canvas.create_text(
            10, 125,
            anchor='nw',
            text=self.title_text,
            fill='white',
            font=font,
        )
        text2 = self.lrg_canvas.create_text(
            10, 145,
            anchor='nw',
            text=TRANSLATION['version'],
            fill='white',
            font=font,
        )

        # Now add shadows behind the text, and draw to the canvas.
        splash, lrg_width, lrg_height = img.make_splash_screen(
            max(self.win.winfo_screenwidth() * 0.6, 500),
            max(self.win.winfo_screenheight() * 0.6, 500),
            base_height=len(self.stages) * 20,
            text1_bbox=self.lrg_canvas.bbox(text1),
            text2_bbox=self.lrg_canvas.bbox(text2),
        )
        self.splash_img = splash  # Keep this alive
        self.lrg_canvas.tag_lower(self.lrg_canvas.create_image(
            0, 0,
            anchor='nw',
            image=splash,
        ))

        self.canvas = [
            (self.lrg_canvas, lrg_width, lrg_height),
            (self.sml_canvas, sml_width, sml_height),
        ]

        for canvas, width, height in self.canvas:
            canvas.create_rectangle(
                width - 40,
                0,
                width - 20,
                20,
                fill='#00785A',
                width=0,
                tags='resize_button',
            )
            # 150, 120, 64
            # Diagonal part of arrow.
            canvas.create_line(
                width - 20 - 4, 4,
                width - 20 - 16, 16,
                fill='black',
                width=2,
                tags='resize_button',
            )
            canvas.tag_bind(
                'resize_button',
                '<Button-1>',
                self.compact_button(
                    canvas is self.lrg_canvas,
                    width,
                    lrg_width if width == sml_width else sml_width,
                ),
            )
        self.sml_canvas.create_line(
            sml_width - 20 - 4, 4,
            sml_width - 20 - 16, 4,
            fill='black',
            width=2,
            tags='resize_button',
        )
        self.sml_canvas.create_line(
            sml_width - 20 - 4, 4,
            sml_width - 20 - 4, 16,
            fill='black',
            width=2,
            tags='resize_button',
        )
        self.lrg_canvas.create_line(
            lrg_width - 20 - 16, 16,
            lrg_width - 20 - 4, 16,
            fill='black',
            width=2,
            tags='resize_button',
        )
        self.lrg_canvas.create_line(
            lrg_width - 20 - 16, 16,
            lrg_width - 20 - 16, 4,
            fill='black',
            width=2,
            tags='resize_button',
        )

        for canvas, width, height in self.canvas:
            canvas['width'] = width
            canvas['height'] = height
            canvas.bind(utils.EVENTS['LEFT_DOUBLE'], self.toggle_compact)

            canvas.create_rectangle(
                width-20,
                0,
                width,
                20,
                fill='#00785A',
                width=0,
                tags='quit_button',
            )
            canvas.create_rectangle(
                width-20,
                0,
                width,
                20,
                fill='#00785A',
                width=0,
                tags='quit_button',
            )
            # 150, 120, 64
            canvas.create_line(
                width-16, 4,
                width-4, 16,
                fill='black',
                width=2,
                tags='quit_button',
            )
            canvas.create_line(
                width-4, 4,
                width-16, 16,
                fill='black',
                width=2,
                tags='quit_button',
            )
            canvas.tag_bind('quit_button', '<Button-1>', self.cancel)

            for ind, (st_id, stage_name) in enumerate(reversed(self.stages), start=1):
                canvas.create_rectangle(
                    20,
                    height - (ind + 0.5) * 20,
                    20,
                    height - (ind - 0.5) * 20,
                    fill='#00785A',  # 0, 120, 90
                    width=0,
                    tags='bar_' + st_id,
                )
                # Border
                canvas.create_rectangle(
                    20,
                    height - (ind + 0.5) * 20,
                    width - 20,
                    height - (ind - 0.5) * 20,
                    outline='#00785A',
                    width=2,
                )
                canvas.create_text(
                    25,
                    height - ind * 20,
                    anchor='w',
                    text=stage_name + ': (0/???)',
                    fill='white',
                    tags='text_' + st_id,
                )
Пример #41
0
    def __init__(self, *args):
        super().__init__(*args)

        self.is_compact = True

        font = Font(
            family='Times',  # Generic special case
            size=-18,  # negative = in pixels
            weight='bold',
        )

        # Must be done late, so we know TK is initialised.
        import img

        logo_img = img.png('BEE2/splash_logo')

        self.lrg_canvas = tk.Canvas(self.win)
        self.sml_canvas = tk.Canvas(
            self.win,
            background='#009678',  # 0, 150, 120
        )

        sml_width = int(min(self.win.winfo_screenwidth() * 0.5, 400))
        sml_height = int(min(self.win.winfo_screenheight() * 0.5, 175))

        self.lrg_canvas.create_image(
            10,
            10,
            anchor='nw',
            image=logo_img,
        )

        self.sml_canvas.create_text(
            sml_width / 2,
            40,
            anchor='n',
            text=self.title_text,
            fill='white',
            font=font,
        )
        self.sml_canvas.create_text(
            sml_width / 2,
            60,
            anchor='n',
            text=TRANSLATION['version'],
            fill='white',
            font=font,
        )

        text1 = self.lrg_canvas.create_text(
            10,
            125,
            anchor='nw',
            text=self.title_text,
            fill='white',
            font=font,
        )
        text2 = self.lrg_canvas.create_text(
            10,
            145,
            anchor='nw',
            text=TRANSLATION['version'],
            fill='white',
            font=font,
        )

        # Now add shadows behind the text, and draw to the canvas.
        splash, lrg_width, lrg_height = img.make_splash_screen(
            max(self.win.winfo_screenwidth() * 0.6, 500),
            max(self.win.winfo_screenheight() * 0.6, 500),
            base_height=len(self.stages) * 20,
            text1_bbox=self.lrg_canvas.bbox(text1),
            text2_bbox=self.lrg_canvas.bbox(text2),
        )
        self.splash_img = splash  # Keep this alive
        self.lrg_canvas.tag_lower(
            self.lrg_canvas.create_image(
                0,
                0,
                anchor='nw',
                image=splash,
            ))

        self.canvas = [
            (self.lrg_canvas, lrg_width, lrg_height),
            (self.sml_canvas, sml_width, sml_height),
        ]

        for canvas, width, height in self.canvas:
            canvas.create_rectangle(
                width - 40,
                0,
                width - 20,
                20,
                fill='#00785A',
                width=0,
                tags='resize_button',
            )
            # 150, 120, 64
            # Diagonal part of arrow.
            canvas.create_line(
                width - 20 - 4,
                4,
                width - 20 - 16,
                16,
                fill='black',
                width=2,
                tags='resize_button',
            )
            canvas.tag_bind(
                'resize_button',
                '<Button-1>',
                self.compact_button(
                    canvas is self.lrg_canvas,
                    width,
                    lrg_width if width == sml_width else sml_width,
                ),
            )
        self.sml_canvas.create_line(
            sml_width - 20 - 4,
            4,
            sml_width - 20 - 16,
            4,
            fill='black',
            width=2,
            tags='resize_button',
        )
        self.sml_canvas.create_line(
            sml_width - 20 - 4,
            4,
            sml_width - 20 - 4,
            16,
            fill='black',
            width=2,
            tags='resize_button',
        )
        self.lrg_canvas.create_line(
            lrg_width - 20 - 16,
            16,
            lrg_width - 20 - 4,
            16,
            fill='black',
            width=2,
            tags='resize_button',
        )
        self.lrg_canvas.create_line(
            lrg_width - 20 - 16,
            16,
            lrg_width - 20 - 16,
            4,
            fill='black',
            width=2,
            tags='resize_button',
        )

        for canvas, width, height in self.canvas:
            canvas['width'] = width
            canvas['height'] = height
            canvas.bind(utils.EVENTS['LEFT_DOUBLE'], self.toggle_compact)

            canvas.create_rectangle(
                width - 20,
                0,
                width,
                20,
                fill='#00785A',
                width=0,
                tags='quit_button',
            )
            canvas.create_rectangle(
                width - 20,
                0,
                width,
                20,
                fill='#00785A',
                width=0,
                tags='quit_button',
            )
            # 150, 120, 64
            canvas.create_line(
                width - 16,
                4,
                width - 4,
                16,
                fill='black',
                width=2,
                tags='quit_button',
            )
            canvas.create_line(
                width - 4,
                4,
                width - 16,
                16,
                fill='black',
                width=2,
                tags='quit_button',
            )
            canvas.tag_bind('quit_button', '<Button-1>', self.cancel)

            for ind, (st_id, stage_name) in enumerate(reversed(self.stages),
                                                      start=1):
                canvas.create_rectangle(
                    20,
                    height - (ind + 0.5) * 20,
                    20,
                    height - (ind - 0.5) * 20,
                    fill='#00785A',  # 0, 120, 90
                    width=0,
                    tags='bar_' + st_id,
                )
                # Border
                canvas.create_rectangle(
                    20,
                    height - (ind + 0.5) * 20,
                    width - 20,
                    height - (ind - 0.5) * 20,
                    outline='#00785A',
                    width=2,
                )
                canvas.create_text(
                    25,
                    height - ind * 20,
                    anchor='w',
                    text=stage_name + ': (0/???)',
                    fill='white',
                    tags='text_' + st_id,
                )
Пример #42
0
def make_pane(tool_frame):
    """Create the compiler options pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Compile Opt',
        name='compiler',
        resize_x=True,
        resize_y=False,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_compiler'),
        tool_col=4,
    )
    window.columnconfigure(0, weight=1)

    thumb_frame = ttk.LabelFrame(
        window,
        text='Thumbnail',
        labelanchor=N,
    )
    thumb_frame.grid(row=0, column=0, sticky=EW)
    thumb_frame.columnconfigure(0, weight=1)

    UI['thumb_auto'] = ttk.Radiobutton(
        thumb_frame,
        text='Auto',
        value='AUTO',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_peti'] = ttk.Radiobutton(
        thumb_frame,
        text='PeTI',
        value='PETI',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_custom'] = ttk.Radiobutton(
        thumb_frame,
        text='Custom:',
        value='CUST',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_label'] = ttk.Label(
        thumb_frame,
        anchor=CENTER,
        cursor=utils.CURSORS['link'],
    )
    UI['thumb_label'].bind(
        utils.EVENTS['LEFT'],
        find_screenshot,
    )

    UI['thumb_cleanup'] = ttk.Checkbutton(
        thumb_frame,
        text='Cleanup old screenshots',
        variable=cleanup_screenshot,
        command=set_screenshot_cleanup,
    )

    UI['thumb_auto'].grid(row=0, column=0, sticky='W')
    UI['thumb_peti'].grid(row=0, column=1, sticky='W')
    UI['thumb_custom'].grid(row=1, column=0, columnspan=2, sticky='NEW')
    UI['thumb_cleanup'].grid(row=3, columnspan=2, sticky='W')
    add_tooltip(
        UI['thumb_auto'],
        "Override the map image to use a screenshot automatically taken"
        "from the beginning of a chamber. Press F5 to take a new "
        "screenshot. If the map has not been previewed recently "
        "(within the last few hours), the default PeTI screenshot "
        "will be used instead.")
    add_tooltip(UI['thumb_peti'],
                "Use the normal editor view for the map preview image.")
    custom_tooltip = (
        "Use a custom image for the map preview image. Click the "
        "screenshot to select.\n"
        "Images will be converted to JPEGs if needed.")
    add_tooltip(
        UI['thumb_custom'],
        custom_tooltip,
    )

    add_tooltip(UI['thumb_label'], custom_tooltip)

    add_tooltip(
        UI['thumb_cleanup'],
        'Automatically delete unused Automatic screenshots. '
        'Disable if you want to keep things in "portal2/screenshots". ')

    if chosen_thumb.get() == 'CUST':
        # Show this if the user has set it before
        UI['thumb_label'].grid(row=2, column=0, columnspan=2, sticky='EW')
    set_screenshot()  # Load the last saved screenshot

    vrad_frame = ttk.LabelFrame(
        window,
        text='Lighting:',
        labelanchor=N,
    )
    vrad_frame.grid(row=1, column=0, sticky=EW)

    UI['light_fast'] = ttk.Radiobutton(
        vrad_frame,
        text='Fast',
        value=0,
        variable=vrad_light_type,
        command=set_vrad_type,
    )
    UI['light_fast'].grid(row=0, column=0)
    UI['light_full'] = ttk.Radiobutton(
        vrad_frame,
        text='Full',
        value=1,
        variable=vrad_light_type,
        command=set_vrad_type,
    )
    UI['light_full'].grid(row=0, column=1)

    add_tooltip(
        UI['light_fast'],
        "Compile with lower-quality, fast lighting. This speeds "
        "up compile times, but does not appear as good. Some "
        "shadows may appear wrong.\n"
        "When publishing, this is ignored.")
    add_tooltip(
        UI['light_full'],
        "Compile with high-quality lighting. This looks correct, "
        "but takes longer to compute. Use if you're arranging lights."
        "When publishing, this is always used.")

    elev_frame = ttk.LabelFrame(
        window,
        text='Spawn at:',
        labelanchor=N,
    )

    elev_frame.grid(row=2, column=0, sticky=EW)
    elev_frame.columnconfigure(0, weight=1)
    elev_frame.columnconfigure(1, weight=1)

    UI['elev_preview'] = ttk.Radiobutton(
        elev_frame,
        text='Entry Door',
        value=0,
        variable=start_in_elev,
        command=set_elev_type,
    )

    UI['elev_elevator'] = ttk.Radiobutton(
        elev_frame,
        text='Elevator',
        value=1,
        variable=start_in_elev,
        command=set_elev_type,
    )

    UI['elev_preview'].grid(row=0, column=0, sticky=W)
    UI['elev_elevator'].grid(row=0, column=1, sticky=W)

    add_tooltip(
        UI['elev_preview'],
        "When previewing in SP, spawn inside the entry elevator. "
        "This also disables the map restarts when you reach the "
        "exit door. Use this to examine the entry and exit corridors.")
    add_tooltip(
        UI['elev_elevator'],
        "When previewing in SP, spawn just before the entry door. "
        "When you reach the exit door, the map will restart.")

    corr_frame = ttk.LabelFrame(
        window,
        text='Corridor:',
        labelanchor=N,
    )
    corr_frame.grid(row=3, column=0, sticky=EW)
    corr_frame.columnconfigure(0, weight=1)
    corr_frame.columnconfigure(1, weight=1)

    UI['corr_sp_entry'] = make_corr_combo(
        corr_frame,
        'sp_entry',
        width=9,
    )

    UI['corr_sp_exit'] = make_corr_combo(
        corr_frame,
        'sp_exit',
        width=9,
    )

    UI['corr_coop'] = make_corr_combo(
        corr_frame,
        'coop',
        width=9,
    )

    UI['corr_sp_entry'].grid(row=1, column=0, sticky=EW)
    UI['corr_sp_exit'].grid(row=1, column=1, sticky=EW)
    UI['corr_coop'].grid(row=2, column=1, sticky=EW)
    ttk.Label(
        corr_frame,
        text='SP Entry:',
        anchor=CENTER,
    ).grid(row=0, column=0, sticky=EW)
    ttk.Label(
        corr_frame,
        text='SP Exit:',
        anchor=CENTER,
    ).grid(row=0, column=1, sticky=EW)
    ttk.Label(
        corr_frame,
        text='Coop:',
        anchor=CENTER,
    ).grid(row=2, column=0, sticky=EW)

    model_frame = ttk.LabelFrame(
        window,
        text='Player Model (SP):',
        labelanchor=N,
    )
    model_frame.grid(row=4, column=0, sticky=EW)
    UI['player_mdl'] = ttk.Combobox(
        model_frame,
        exportselection=0,
        textvariable=player_model_var,
        values=PLAYER_MODEL_ORDER,
        width=20,
    )
    # Users can only use the dropdown
    UI['player_mdl'].state(['readonly'])
    UI['player_mdl'].grid(row=0, column=0, sticky=EW)

    UI['player_mdl'].bind('<<ComboboxSelected>>', set_model)
    model_frame.columnconfigure(0, weight=1)

    count_frame = ttk.LabelFrame(
        window,
        text='Last Compile:',
        labelanchor=N,
    )

    count_frame.grid(row=5, column=0, sticky=EW)
    count_frame.columnconfigure(0, weight=1)
    count_frame.columnconfigure(2, weight=1)

    ttk.Label(
        count_frame,
        text='Entity',
        anchor=N,
    ).grid(row=0, column=0, columnspan=3, sticky=EW)

    UI['count_ent'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_ENTS,
        variable=count_ents,
        length=120,
    )
    UI['count_ent'].grid(
        row=1,
        column=0,
        columnspan=3,
        sticky=EW,
        padx=5,
    )

    ttk.Label(
        count_frame,
        text='Overlay',
        anchor=CENTER,
    ).grid(row=2, column=0, sticky=EW)
    UI['count_over'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_OVERLAY,
        variable=count_overlay,
        length=50,
    )
    UI['count_over'].grid(row=3, column=0, sticky=EW, padx=5)

    ttk.Button(
        count_frame,
        image=png.png('icons/tool_sub'),
        command=refresh_counts,
    ).grid(row=3, column=1)

    ttk.Label(
        count_frame,
        text='Brush',
        anchor=CENTER,
    ).grid(row=2, column=2, sticky=EW)
    UI['count_brush'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_BRUSH,
        variable=count_brush,
        length=50,
    )
    UI['count_brush'].grid(row=3, column=2, sticky=EW, padx=5)

    UI['view_logs'] = ttk.Button(
        count_frame,
        text='View Logs',
    )
    UI['view_logs'].grid(row=4, column=0, columnspan=3, sticky=EW)

    refresh_counts(reload=False)
Пример #43
0
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Style Properties',
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_stylevar'),
        tool_col=2,
    )

    UI['style_can'] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        window,
        orient=VERTICAL,
        command=UI['style_can'].yview,
        )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set
    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text="All:")
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text="Selected Style:")
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
        ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text="Other Styles:")
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text='No Options!',
        font='TkMenuFont',
        justify='center',
        )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text='None!',
        font='TkMenuFont',
        justify='center',
        )

    for pos, (var_id, name, default) in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var_id] = IntVar(
            value=GEN_OPTS.get_bool('StyleVar', var_id, default)
        )
        checkbox_special[var_id] = ttk.Checkbutton(
            frame_all,
            variable=tk_vars[var_id],
            text=name,
            command=functools.partial(set_stylevar, var_id)
            )
        checkbox_special[var_id].grid(row=pos, column=0, sticky="W", padx=3)

    for var in var_list:
        tk_vars[var.id] = IntVar(value=var.default)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            'command': functools.partial(set_stylevar, var.id)
            }
        checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
        checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
        )
    ttk.Sizegrip(
        window,
        cursor="sb_v_double_arrow",
        ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)

    # Scroll globally even if canvas is not selected.
    window.bind(
        "<MouseWheel>",
        lambda e: scroll(int(-1*(e.delta/120))),
        )
    window.bind(
        "<Button-4>",
        lambda e: scroll(1),
        )
    window.bind(
        "<Button-5>",
        lambda e: scroll(-1),
        )
Пример #44
0
def init_widgets():
    """Initiallise all the window components."""
    global prop_window
    prop_window = Toplevel(TK_ROOT)
    prop_window.overrideredirect(1)
    prop_window.resizable(False, False)
    prop_window.transient(master=TK_ROOT)
    prop_window.attributes('-topmost', 1)
    prop_window.withdraw()  # starts hidden

    f = ttk.Frame(prop_window, relief="raised", borderwidth="4")
    f.grid(row=0, column=0)

    ttk.Label(
        f,
        text="Properties:",
        anchor="center",
    ).grid(
        row=0,
        column=0,
        columnspan=3,
        sticky="EW",
    )

    wid['name'] = ttk.Label(f, text="", anchor="center")
    wid['name'].grid(row=1, column=0, columnspan=3, sticky="EW")

    wid['ent_count'] = ttk.Label(
        f,
        text="",
        anchor="e",
        compound="left",
        image=png.spr('gear_ent'),
    )
    wid['ent_count'].grid(row=0, column=2, rowspan=2, sticky=E)
    tooltip.add_tooltip(
        wid['ent_count'],
        'The number of entities used for this item. The Source engine limits '
        'this to 2048 in total. This provides a guide to how many of these '
        'items can be placed in a map at once.'
    )

    wid['author'] = ttk.Label(f, text="", anchor="center", relief="sunken")
    wid['author'].grid(row=2, column=0, columnspan=3, sticky="EW")

    sub_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    sub_frame.grid(column=0, columnspan=3, row=3)
    for i in range(5):
        wid['subitem', i] = ttk.Label(
            sub_frame,
            image=png.png('BEE2/alpha_64'),
        )
        wid['subitem', i].grid(row=0, column=i)
        utils.bind_leftclick(
            wid['subitem', i],
            functools.partial(sub_sel, i),
        )
        utils.bind_rightclick(
            wid['subitem', i],
            functools.partial(sub_open, i),
        )

    wid['wip_dep'] = ttk.Label(f, text='', anchor="nw")
    wid['wip_dep'].grid(row=4, column=0, sticky="NW")

    ttk.Label(f, text="Description:", anchor="sw").grid(
        row=4,
        column=0,
        sticky="SW",
    )

    spr_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    spr_frame.grid(column=1, columnspan=2, row=4, sticky=W)
    # sprites: inputs, outputs, rotation handle, occupied/embed state,
    # desiredFacing
    for spr_id in SPR:
        wid['sprite', spr_id] = sprite = ttk.Label(
            spr_frame,
            image=png.spr('ap_grey'),
            relief="raised",
        )
        sprite.grid(row=0, column=spr_id.value)
        tooltip.add_tooltip(sprite)

    desc_frame = ttk.Frame(f, borderwidth=4, relief="sunken")
    desc_frame.grid(row=5, column=0, columnspan=3, sticky="EW")
    desc_frame.columnconfigure(0, weight=1)

    wid['desc'] = tkRichText(desc_frame, width=40, height=8)
    wid['desc'].grid(row=0, column=0, sticky="EW")

    desc_scroll = tk_tools.HidingScroll(
        desc_frame,
        orient=VERTICAL,
        command=wid['desc'].yview,
        )
    wid['desc']['yscrollcommand'] = desc_scroll.set
    desc_scroll.grid(row=0, column=1, sticky="NS")

    def show_more_info():
        url = selected_item.url
        if url is not None:
            try:
                webbrowser.open(url, new=OPEN_IN_TAB, autoraise=True)
            except webbrowser.Error:
                if messagebox.askyesno(
                        icon="error",
                        title="BEE2 - Error",
                        message='Failed to open a web browser. Do you wish for '
                                'the URL to be copied to the clipboard '
                                'instead?',
                        detail='"{!s}"'.format(url),
                        parent=prop_window
                        ):
                    LOGGER.info("Saving {} to clipboard!", url)
                    TK_ROOT.clipboard_clear()
                    TK_ROOT.clipboard_append(url)
            # Either the webbrowser or the messagebox could cause the
            # properties to move behind the main window, so hide it
            # so it doesn't appear there.
            hide_context(None)

    wid['moreinfo'] = ttk.Button(f, text="More Info>>", command=show_more_info)
    wid['moreinfo'].grid(row=6, column=2, sticky=E)
    tooltip.add_tooltip(wid['moreinfo'])

    menu_info = Menu(wid['moreinfo'])
    menu_info.add_command(label='', state='disabled')

    def show_item_props():
        snd.fx('expand')
        itemPropWin.show_window(
            selected_item.get_properties(),
            wid['changedefaults'],
            selected_sub_item.name,
        )

    wid['changedefaults'] = ttk.Button(
        f,
        text="Change Defaults...",
        command=show_item_props,
        )
    wid['changedefaults'].grid(row=6, column=1)
    tooltip.add_tooltip(
        wid['changedefaults'],
        'Change the default settings for this item when placed.'
    )

    wid['variant'] = ttk.Combobox(
        f,
        values=['VERSION'],
        exportselection=0,
        # On Mac this defaults to being way too wide!
        width=7 if utils.MAC else None,
    )
    wid['variant'].state(['readonly'])  # Prevent directly typing in values
    wid['variant'].bind('<<ComboboxSelected>>', set_item_version)
    wid['variant'].current(0)
    wid['variant'].grid(row=6, column=0, sticky=W)

    itemPropWin.init(hide_item_props)
Пример #45
0
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title=_('Style Properties'),
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_stylevar'),
        tool_col=3,
    )

    UI['style_can'] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        window,
        orient=VERTICAL,
        command=UI['style_can'].yview,
    )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set

    utils.add_mousewheel(UI['style_can'], window)

    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text=_("All:"))
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text=_("Selected Style:"))
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
    ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text=_("Other Styles:"))
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text=_('No Options!'),
        font='TkMenuFont',
        justify='center',
    )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text=_('None!'),
        font='TkMenuFont',
        justify='center',
    )

    all_pos = 0
    for all_pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = IntVar(
            value=GEN_OPTS.get_bool('StyleVar', var.id, var.default))
        checkbox_all[var.id] = ttk.Checkbutton(frame_all,
                                               variable=tk_vars[var.id],
                                               text=var.name,
                                               command=functools.partial(
                                                   set_stylevar, var.id))
        checkbox_all[var.id].grid(row=all_pos, column=0, sticky="W", padx=3)

        tooltip.add_tooltip(
            checkbox_all[var.id],
            make_desc(var, is_hardcoded=True),
        )

    for var in VAR_LIST:
        tk_vars[var.id] = IntVar(value=var.enabled)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            'command': functools.partial(set_stylevar, var.id)
        }
        desc = make_desc(var)
        if var.applies_to_all():
            # Available in all styles - put with the hardcoded variables.
            all_pos += 1

            checkbox_all[var.id] = check = ttk.Checkbutton(frame_all, **args)
            check.grid(row=all_pos, column=0, sticky="W", padx=3)
            tooltip.add_tooltip(check, desc)
        else:
            # Swap between checkboxes depending on style.
            checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
            checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
            tooltip.add_tooltip(
                checkbox_chosen[var.id],
                desc,
            )
            tooltip.add_tooltip(
                checkbox_other[var.id],
                desc,
            )

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
    )

    if utils.USE_SIZEGRIP:
        ttk.Sizegrip(
            window,
            cursor=utils.CURSORS['stretch_vert'],
        ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)
Пример #46
0
def make_pane(tool_frame: Frame, menu_bar: Menu):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        title=_('Style/Item Properties'),
        name='style',
        menu_bar=menu_bar,
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=img.png('icons/win_stylevar'),
        tool_col=3,
    )

    UI['nbook'] = nbook = ttk.Notebook(window)

    nbook.grid(row=0, column=0, sticky=NSEW)
    window.rowconfigure(0, weight=1)
    window.columnconfigure(0, weight=1)
    nbook.enable_traversal()

    stylevar_frame = ttk.Frame(nbook)
    stylevar_frame.rowconfigure(0, weight=1)
    stylevar_frame.columnconfigure(0, weight=1)
    nbook.add(stylevar_frame, text=_('Styles'))

    UI['style_can'] = Canvas(stylevar_frame, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        stylevar_frame,
        orient=VERTICAL,
        command=UI['style_can'].yview,
    )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set

    utils.add_mousewheel(UI['style_can'], stylevar_frame)

    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text=_("All:"))
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text=_("Selected Style:"))
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
    ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text=_("Other Styles:"))
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text=_('No Options!'),
        font='TkMenuFont',
        justify='center',
    )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text=_('None!'),
        font='TkMenuFont',
        justify='center',
    )

    all_pos = 0
    for all_pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = int_var = IntVar(value=var.default)
        checkbox_all[var.id] = ttk.Checkbutton(
            frame_all,
            variable=int_var,
            text=var.name,
        )
        checkbox_all[var.id].grid(row=all_pos, column=0, sticky="W", padx=3)

        # Special case - this needs to refresh the filter when swapping,
        # so the items disappear or reappear.
        if var.id == 'UnlockDefault':

            def cmd():
                update_filter()

            checkbox_all[var.id]['command'] = cmd

        tooltip.add_tooltip(
            checkbox_all[var.id],
            make_desc(var, is_hardcoded=True),
        )

    for var in VAR_LIST:
        tk_vars[var.id] = IntVar(value=var.enabled)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
        }
        desc = make_desc(var)
        if var.applies_to_all():
            # Available in all styles - put with the hardcoded variables.
            all_pos += 1

            checkbox_all[var.id] = check = ttk.Checkbutton(frame_all, **args)
            check.grid(row=all_pos, column=0, sticky="W", padx=3)
            tooltip.add_tooltip(check, desc)
        else:
            # Swap between checkboxes depending on style.
            checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
            checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
            tooltip.add_tooltip(
                checkbox_chosen[var.id],
                desc,
            )
            tooltip.add_tooltip(
                checkbox_other[var.id],
                desc,
            )

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
    )

    if utils.USE_SIZEGRIP:
        ttk.Sizegrip(
            window,
            cursor=utils.CURSORS['stretch_vert'],
        ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)

    item_config_frame = ttk.Frame(nbook)
    nbook.add(item_config_frame, text=_('Items'))
    itemconfig.make_pane(item_config_frame)
Пример #47
0
    def __init__(self, *stages):
        super().__init__(stages)
        self.stage_names = {}

        self.splash, width, height = img.get_splash_screen(
            max(self.winfo_screenwidth() * 0.6, 500),
            max(self.winfo_screenheight() * 0.6, 500),
            base_height=len(self.stages) * 20,
        )
        self.height = height
        self.width = width

        self.canvas = canvas = Canvas(
            self,
            width=width,
            height=height,
        )
        canvas.grid(row=0, column=0)
        # Splash screen...
        canvas.create_image(
            0, 0,
            anchor='nw',
            image=self.splash,
        )
        canvas.create_image(
            10, 10,
            anchor='nw',
            image=img.png('BEE2/splash_logo'),
        )

        self.disp_font = font = Font(
            family='Times',  # Generic special case
            size=-18,  # negative = in pixels
            weight='bold',
        )

        canvas.create_text(
            10, 125,
            anchor='nw',
            text=_('Better Extended Editor for Portal 2'),
            fill='white',
            font=font,
        )
        canvas.create_text(
            10, 145,
            anchor='nw',
            text=_('Version: ') + utils.BEE_VERSION,
            fill='white',
            font=font,
        )

        for ind, (st_id, stage_name) in enumerate(reversed(self.stages), start=1):
            self.bar_val[st_id] = 0
            self.maxes[st_id] = 10
            self.stage_names[st_id] = stage_name
            canvas.create_rectangle(
                20,
                height - (ind + 0.5) * 20,
                20,
                height - (ind - 0.5) * 20,
                fill='#00785A',  # 0, 120, 90
                width=0,
                tags='bar_' + st_id,
            )
            # Border
            canvas.create_rectangle(
                20,
                height - (ind + 0.5) * 20,
                width - 20,
                height - (ind - 0.5) * 20,
                outline='#00785A',
                width=2,
            )
            canvas.create_text(
                25,
                height - ind * 20,
                anchor='w',
                text=stage_name + ': (0/???)',
                fill='white',
                tags='text_' + st_id,
            )
Пример #48
0
def run_screen(
    cmd_source,
    stages,
    # Pass in various bits of translated text
    # so we don't need to do it here.
    trans_title,
    trans_version,
    trans_skipped,
):
    """Runs in the other process, with an end of a pipe for input."""

    window = tk.Tk()
    window.wm_overrideredirect(True)
    window.attributes('-topmost', 1)

    window['cursor'] = utils.CURSORS['wait']

    stage_values = {}
    stage_maxes = {}
    stage_names = {}

    import img

    logo_img = img.png('BEE2/splash_logo')

    canvas = tk.Canvas(window)
    canvas.grid(row=0, column=0)
    canvas.create_image(
        10,
        10,
        anchor='nw',
        image=logo_img,
    )

    font = Font(
        family='Times',  # Generic special case
        size=-18,  # negative = in pixels
        weight='bold',
    )

    text1 = canvas.create_text(
        10,
        125,
        anchor='nw',
        text=trans_title,
        fill='white',
        font=font,
    )
    text2 = canvas.create_text(
        10,
        145,
        anchor='nw',
        text=trans_version,
        fill='white',
        font=font,
    )

    # Now add shadows behind the text, and draw to the canvas.
    splash, canvas['width'], canvas[
        'height'] = splash, width, height = img.make_splash_screen(
            max(window.winfo_screenwidth() * 0.6, 500),
            max(window.winfo_screenheight() * 0.6, 500),
            base_height=len(stages) * 20,
            text1_bbox=canvas.bbox(text1),
            text2_bbox=canvas.bbox(text2),
        )
    canvas.tag_lower(canvas.create_image(
        0,
        0,
        anchor='nw',
        image=splash,
    ))
    canvas.splash_img = splash  # Keep this alive

    for ind, (st_id, stage_name) in enumerate(reversed(stages), start=1):
        stage_values[st_id] = 0
        stage_maxes[st_id] = 10
        stage_names[st_id] = stage_name
        canvas.create_rectangle(
            20,
            height - (ind + 0.5) * 20,
            20,
            height - (ind - 0.5) * 20,
            fill='#00785A',  # 0, 120, 90
            width=0,
            tags='bar_' + st_id,
        )
        # Border
        canvas.create_rectangle(
            20,
            height - (ind + 0.5) * 20,
            width - 20,
            height - (ind - 0.5) * 20,
            outline='#00785A',
            width=2,
        )
        canvas.create_text(
            25,
            height - ind * 20,
            anchor='w',
            text=stage_name + ': (0/???)',
            fill='white',
            tags='text_' + st_id,
        )

    def bar_length(stage, fraction):
        """Set a progress bar to this fractional length."""
        x1, y1, x2, y2 = canvas.coords('bar_' + stage)
        canvas.coords(
            'bar_' + stage,
            20,
            y1,
            20 + round(fraction * (width - 40)),
            y2,
        )

    def set_nums(stage):
        canvas.itemconfig('text_' + stage,
                          text='{}: ({}/{})'.format(
                              stage_names[stage],
                              stage_values[stage],
                              stage_maxes[stage],
                          ))
        bar_length(stage, stage_values[stage] / stage_maxes[stage])

    def set_length(stage, num):
        """Set the number of items in a stage."""
        stage_maxes[stage] = num
        set_nums(stage)

        canvas.delete('tick_' + stage)

        if num == 0:
            return  # No ticks

        # Draw the ticks in...
        _, y1, _, y2 = canvas.coords('bar_' + stage)

        dist = (width - 40) / num
        if round(dist) <= 1:
            # Don't have ticks if they're right next to each other
            return
        tag = 'tick_' + stage
        for i in range(num):
            pos = int(20 + dist * i)
            canvas.create_line(
                pos,
                y1,
                pos,
                y2,
                fill='#00785A',
                tags=tag,
            )
        canvas.tag_lower('tick_' + stage, 'bar_' + stage)

    def skip_stage(stage):
        """Skip over this stage of the loading process."""
        stage_values[stage] = 0
        stage_maxes[stage] = 0
        canvas.itemconfig(
            'text_' + stage,
            text=stage_names[stage] + ': ' + trans_skipped,
        )
        bar_length(stage, 1)  # Force stage to be max filled.
        canvas.delete('tick_' + stage)
        canvas.update()

    def check_queue():
        """Update stages from the parent process."""
        while cmd_source.poll():  # Pop off all the values.
            stage, operation, value = cmd_source.recv()
            if operation == 'kill':
                # Destroy everything
                window.destroy()
                # mainloop() will quit, this function will too, and
                # all our stuff will die.
                return
            elif operation == 'hide':
                window.withdraw()
            elif operation == 'show':
                window.deiconify()
            elif operation == 'value':
                stage_values[stage] = value
                set_nums(stage)
            elif operation == 'length':
                set_length(stage, value)
            elif operation == 'skip':
                skip_stage(stage)
            else:
                raise ValueError('Bad operation {!r}!'.format(operation))

        # Continually re-run this function in the TK loop.
        window.after_idle(check_queue)

    # We have to implement dragging ourselves.
    x = y = None

    def move_start(event):
        """Record offset of mouse on click"""
        nonlocal x, y
        x = event.x
        y = event.y
        window['cursor'] = utils.CURSORS['move_item']

    def move_stop(event):
        """Clear values when releasing."""
        window['cursor'] = utils.CURSORS['wait']
        nonlocal x, y
        x = y = None

    def move_motion(event):
        """Move the window when moving the mouse."""
        if x is None or y is None:
            return
        window.geometry('+{x:g}+{y:g}'.format(
            x=window.winfo_x() + (event.x - x),
            y=window.winfo_y() + (event.y - y),
        ))

    window.bind('<Button-1>', move_start)
    window.bind('<ButtonRelease-1>', move_stop)
    window.bind('<B1-Motion>', move_motion)

    window.deiconify()
    window.lift()
    window.update()  # Force an update so the reqwidth is correct
    window.geometry('+{x:g}+{y:g}'.format(
        x=(window.winfo_screenwidth() - window.winfo_reqwidth()) // 2,
        y=(window.winfo_screenheight() - window.winfo_reqheight()) // 2,
    ))

    window.after(10, check_queue)
    window.mainloop()  # Infinite loop until we've quit here...
Пример #49
0
from tkinter import *  # ui library
from tkinter import font
from tkinter import ttk  # themed ui components that match the OS
import functools
import math

import img  # png library for TKinter
from richTextBox import tkRichText
import utils

ICON_SIZE = 96  # Size of the selector win icons
ITEM_WIDTH = ICON_SIZE+16
ITEM_HEIGHT = ICON_SIZE+51

# The larger error icon used if an image is not found
err_icon = img.png('BEE2/error_96', resize_to=ICON_SIZE)


def _NO_OP(*args):
    """The default callback, triggered whenever the chosen item is changed."""
    pass


class Item:
    """An item on the panel.

    - name: The item ID, used to distinguish it from others.
    - longName: The full item name. This can be very long. If not set,
      this will be the same as the short name.
    - shortName: A shortened version of the full name. This should be <= 20
      characters.
Пример #50
0
def make_pane(tool_frame):
    """Create the compiler options pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Compile Options',
        name='compiler',
        resize_x=False,
        resize_y=False,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_compiler'),
        tool_col=3,
    )
    window.columnconfigure(0, weight=1)

    thumb_frame = ttk.LabelFrame(
        window,
        text='Thumbnail',
        labelanchor=N,
    )
    thumb_frame.grid(row=0, column=0, sticky=EW)
    thumb_frame.columnconfigure(0, weight=1)

    UI['thumb_auto'] = ttk.Radiobutton(
        thumb_frame,
        text='Auto',
        value='AUTO',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_peti'] = ttk.Radiobutton(
        thumb_frame,
        text='PeTI',
        value='PETI',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    cust_frame = ttk.Frame(thumb_frame)
    cust_frame.columnconfigure(1, weight=1)

    UI['thumb_custom'] = ttk.Radiobutton(
        cust_frame,
        text='',
        value='CUST',
        variable=chosen_thumb,
        command=set_screen_type,
    )

    UI['thumb_custom_file'] = ttk.Entry(
        cust_frame,
        cursor='arrow',
        textvariable=cust_file_loc_var,
        width=15,
    )
    UI['thumb_custom_file'].bind("<Button-1>", find_screenshot)
    UI['thumb_custom_file'].bind("<Key>", set_screenshot_text)

    UI['thumb_custom_btn'] = ttk.Button(
        cust_frame,
        text="...",
        width=1.5,
        command=find_screenshot,
    )

    UI['thumb_auto'].grid(row=0, column=0, sticky=W)
    UI['thumb_peti'].grid(row=0, column=1, sticky=W)
    cust_frame.grid(row=1, column=0, columnspan=2, sticky=EW)
    UI['thumb_custom'].grid(row=0, column=0, sticky=W)
    UI['thumb_custom_file'].grid(row=0, column=1, sticky=EW)
    UI['thumb_custom_btn'].grid(row=0, column=2, sticky=EW)

    elev_frame = ttk.LabelFrame(
        window,
        text='Spawn at:',
        labelanchor=N,
    )

    elev_frame.grid(row=1, column=0, sticky=EW)

    UI['elev_preview'] = ttk.Radiobutton(
        elev_frame,
        text='Entry Door',
        value=0,
        variable=start_in_elev,
        command=set_elev_type,
    )

    UI['elev_elevator'] = ttk.Radiobutton(
        elev_frame,
        text='Elevator',
        value=1,
        variable=start_in_elev,
        command=set_elev_type,
    )

    UI['elev_preview'].grid(row=0, column=0, sticky=W)
    UI['elev_elevator'].grid(row=0, column=1, sticky=W)

    model_frame = ttk.LabelFrame(
        window,
        text='Player Model (SP):',
        labelanchor=N,
    )
    model_frame.grid(row=2, column=0, sticky=EW)
    UI['player_mdl'] = ttk.Combobox(
        model_frame,
        exportselection=0,
        textvariable=player_model_var,
        values=PLAYER_MODEL_ORDER,
    )
    # Users can only use the dropdown
    UI['player_mdl'].state(['readonly'])
    UI['player_mdl'].grid(row=0, column=0, sticky=EW)

    UI['player_mdl'].bind('<<ComboboxSelected>>', set_model)

    count_frame = ttk.LabelFrame(
        window,
        text='Last Compile:',
        labelanchor=N,
    )

    count_frame.grid(row=3, column=0)

    ttk.Label(
        count_frame,
        text='Entity',
        anchor=N,
    ).grid(row=0, column=0, columnspan=3, sticky=EW)

    UI['count_ent'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_ENTS,
        variable=count_ents,
        length=120,
    )
    UI['count_ent'].grid(
        row=1,
        column=0,
        columnspan=3,
        sticky=EW,
        padx=5,
    )


    ttk.Label(
        count_frame,
        text='Overlay',
        anchor=CENTER,
    ).grid(row=2, column=0, sticky=EW)
    UI['count_over'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_OVERLAY,
        variable=count_overlay,
        length=50,
    )
    UI['count_over'].grid(row=3, column=0, sticky=EW, padx=5)

    ttk.Button(
        count_frame,
        image=png.png('icons/tool_sub'),
        command=refresh_counts,
    ).grid(row=3, column=1)


    ttk.Label(
        count_frame,
        text='Brush',
        anchor=CENTER,
    ).grid(row=2, column=2, sticky=EW)
    UI['count_brush'] = ttk.Progressbar(
        count_frame,
        maximum=MAX_BRUSH,
        variable=count_brush,
        length=50,
    )
    UI['count_brush'].grid(row=3, column=2, sticky=EW, padx=5)

    UI['view_logs'] = ttk.Button(
        count_frame,
        text='View Logs',
    )
    UI['view_logs'].grid(row=4, column=0, columnspan=3, sticky=EW)

    refresh_counts(reload=False)
Пример #51
0
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Style Properties',
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_stylevar'),
        tool_col=3,
    )

    UI['style_can'] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        window,
        orient=VERTICAL,
        command=UI['style_can'].yview,
    )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set
    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text="All:")
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text="Selected Style:")
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
    ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text="Other Styles:")
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text='No Options!',
        font='TkMenuFont',
        justify='center',
    )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text='None!',
        font='TkMenuFont',
        justify='center',
    )

    for pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = IntVar(
            value=GEN_OPTS.get_bool('StyleVar', var.id, var.enabled))
        checkbox_special[var.id] = ttk.Checkbutton(frame_all,
                                                   variable=tk_vars[var.id],
                                                   text=var.name,
                                                   command=functools.partial(
                                                       set_stylevar, var.id))
        checkbox_special[var.id].grid(row=pos, column=0, sticky="W", padx=3)

        if var.desc:
            tooltip.add_tooltip(
                checkbox_special[var.id],
                var.desc,
            )

    for var in var_list:
        tk_vars[var.id] = IntVar(value=var.default)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            'command': functools.partial(set_stylevar, var.id)
        }
        checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
        checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
        if var.desc:
            tooltip.add_tooltip(
                checkbox_chosen[var.id],
                var.desc,
            )
            tooltip.add_tooltip(
                checkbox_other[var.id],
                var.desc,
            )

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
    )
    ttk.Sizegrip(
        window,
        cursor=utils.CURSORS['stretch_vert'],
    ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)

    # Scroll globally even if canvas is not selected.
    if utils.WIN:
        window.bind(
            "<MouseWheel>",
            lambda e: scroll(int(-1 * (e.delta / 120))),
        )
    elif utils.MAC:
        window.bind(
            "<Button-4>",
            lambda e: scroll(1),
        )
        window.bind(
            "<Button-5>",
            lambda e: scroll(-1),
        )