playscii/ui_menu_pulldown_item.py

1033 lines
26 KiB
Python

from renderable import LAYER_VIS_DIM, LAYER_VIS_FULL, LAYER_VIS_NONE
from ui_tool import (
EraseTool,
FillTool,
GrabTool,
PasteTool,
PencilTool,
RotateTool,
SelectTool,
TextTool,
)
#
# specific pulldown menu items, eg File > Save, Edit > Copy
#
class PulldownMenuItem:
# label that displays for this item
label = "Test Menu Item"
# bindable command we look up from InputLord to get binding text from
command = "test_command"
# if not None, passed to button's cb_arg
cb_arg = None
# if True, pulldown button creation process won't auto-pad
no_pad = False
# if True, item will never be dimmed
always_active = False
# if True, pulldown will close when this item is selected
close_on_select = False
# item is allowed in Art Mode
art_mode_allowed = True
# item is allowed in Game Mode
game_mode_allowed = True
def should_dim(app):
"returns True if this item should be dimmed based on current application state"
# so many commands are inapplicable with no active art, default to dimming an
# item if this is the case
return app.ui.active_art is None
def get_label(app):
"returns custom generated label based on app state"
return None
class SeparatorItem(PulldownMenuItem):
"menu separator, non-interactive and handled specially by menu drawing"
pass
class ArtModePulldownMenuItem(PulldownMenuItem):
# unless overridden, art mode items not allowed in game mode
game_mode_allowed = False
#
# file menu
#
class FileNewItem(ArtModePulldownMenuItem):
label = "New…"
command = "new_art"
always_active = True
class FileOpenItem(ArtModePulldownMenuItem):
label = "Open…"
command = "open_art"
always_active = True
class FileSaveItem(ArtModePulldownMenuItem):
label = "Save"
command = "save_current"
def should_dim(app):
return not app.ui.active_art or not app.ui.active_art.unsaved_changes
class FileSaveAsItem(ArtModePulldownMenuItem):
label = "Save As…"
command = "save_art_as"
def should_dim(app):
return app.ui.active_art is None
class FileCloseItem(ArtModePulldownMenuItem):
label = "Close"
command = "close_art"
def should_dim(app):
return app.ui.active_art is None
class FileRevertItem(ArtModePulldownMenuItem):
label = "Revert"
command = "revert_art"
def should_dim(app):
return app.ui.active_art is None or not app.ui.active_art.unsaved_changes
class FileImportItem(ArtModePulldownMenuItem):
label = "Import…"
command = "import_file"
always_active = True
class FileExportItem(ArtModePulldownMenuItem):
label = "Export…"
command = "export_file"
def should_dim(app):
return app.ui.active_art is None
class FileExportLastItem(ArtModePulldownMenuItem):
label = "Export last"
command = "export_file_last"
def should_dim(app):
return app.ui.active_art is None
class FileConvertImageItem(ArtModePulldownMenuItem):
label = "Convert Image…"
command = "convert_image"
def should_dim(app):
return app.ui.active_art is None
class FileQuitItem(ArtModePulldownMenuItem):
label = "Quit"
command = "quit"
always_active = True
game_mode_allowed = True
#
# edit menu
#
class EditUndoItem(ArtModePulldownMenuItem):
label = "Undo"
command = "undo"
def should_dim(app):
return (
not app.ui.active_art
or len(app.ui.active_art.command_stack.undo_commands) == 0
)
class EditRedoItem(ArtModePulldownMenuItem):
label = "Redo"
command = "redo"
def should_dim(app):
return (
not app.ui.active_art
or len(app.ui.active_art.command_stack.redo_commands) == 0
)
class EditCutItem(ArtModePulldownMenuItem):
label = "Cut"
command = "cut_selection"
def should_dim(app):
return len(app.ui.select_tool.selected_tiles) == 0
class EditCopyItem(ArtModePulldownMenuItem):
label = "Copy"
command = "copy_selection"
def should_dim(app):
return len(app.ui.select_tool.selected_tiles) == 0
class EditPasteItem(ArtModePulldownMenuItem):
label = "Paste"
command = "select_paste_tool"
def should_dim(app):
return len(app.ui.clipboard) == 0
class EditDeleteItem(ArtModePulldownMenuItem):
label = "Clear"
command = "erase_selection_or_art"
class EditSelectAllItem(ArtModePulldownMenuItem):
label = "Select All"
command = "select_all"
class EditSelectNoneItem(ArtModePulldownMenuItem):
label = "Select None"
command = "select_none"
class EditSelectInvertItem(ArtModePulldownMenuItem):
label = "Invert Selection"
command = "select_invert"
class EditPreferences(ArtModePulldownMenuItem):
label = "Preferences…"
command = "edit_cfg"
#
# tool menu
#
class ToolTogglePickerItem(ArtModePulldownMenuItem):
# two spaces in front of each label to leave room for mark
label = "Show char/color picker"
command = "toggle_picker"
class ToolTogglePickerHoldItem(ArtModePulldownMenuItem):
label = "blah"
command = "toggle_picker_hold"
def get_label(app):
return "Picker toggle key: {}".format(
["press", "hold"][app.ui.popup_hold_to_show]
)
class ToolSwapSelectedColors(ArtModePulldownMenuItem):
label = "Swap selected fg/bg colors"
command = "swap_fg_bg_colors"
class ToolToggleArtToolbar(ArtModePulldownMenuItem):
label = " Show toolbar"
command = "toggle_art_toolbar"
def should_mark(ui):
return ui.art_toolbar.visible
class ToolPaintItem(ArtModePulldownMenuItem):
# two spaces in front of each label to leave room for mark
label = " {}".format(PencilTool.button_caption)
command = "select_pencil_tool"
class ToolEraseItem(ArtModePulldownMenuItem):
label = " {}".format(EraseTool.button_caption)
command = "select_erase_tool"
class ToolRotateItem(ArtModePulldownMenuItem):
label = " {}".format(RotateTool.button_caption)
command = "select_rotate_tool"
class ToolGrabItem(ArtModePulldownMenuItem):
label = " {}".format(GrabTool.button_caption)
command = "select_grab_tool"
class ToolTextItem(ArtModePulldownMenuItem):
label = " {}".format(TextTool.button_caption)
command = "select_text_tool"
class ToolSelectItem(ArtModePulldownMenuItem):
label = " {}".format(SelectTool.button_caption)
command = "select_select_tool"
class ToolPasteItem(ArtModePulldownMenuItem):
label = " {}".format(PasteTool.button_caption)
command = "select_paste_tool"
class ToolFillItem(ArtModePulldownMenuItem):
label = " {}".format(FillTool.button_caption)
command = "select_fill_tool"
class ToolIncreaseBrushSizeItem(ArtModePulldownMenuItem):
label = "blah"
command = "increase_brush_size"
def should_dim(app):
# dim this item for tools where brush size doesn't apply
if not app.ui.active_art or not app.ui.selected_tool.brush_size:
return True
def get_label(app):
if not app.ui.selected_tool.brush_size:
return "Increase brush size"
size = app.ui.selected_tool.brush_size + 1
return "Increase brush size to {}".format(size)
class ToolDecreaseBrushSizeItem(ArtModePulldownMenuItem):
label = "blah"
command = "decrease_brush_size"
def should_dim(app):
if not app.ui.active_art or not app.ui.selected_tool.brush_size:
return True
return app.ui.selected_tool.brush_size <= 1
def get_label(app):
if not app.ui.selected_tool.brush_size:
return "Decrease brush size"
size = app.ui.selected_tool.brush_size - 1
return "Decrease brush size to {}".format(size)
class ToolSettingsItem(ArtModePulldownMenuItem):
# base class for tool settings toggle items
def should_dim(app):
# blacklist specific tools
return not app.ui.active_art or type(app.ui.selected_tool) in [SelectTool]
class ToolToggleAffectsCharItem(ToolSettingsItem):
label = " Affects: character"
command = "toggle_affects_char"
def should_mark(ui):
return ui.selected_tool.affects_char
class ToolToggleAffectsFGItem(ToolSettingsItem):
label = " Affects: foreground color"
command = "toggle_affects_fg"
def should_mark(ui):
return ui.selected_tool.affects_fg_color
class ToolToggleAffectsBGItem(ToolSettingsItem):
label = " Affects: background color"
command = "toggle_affects_bg"
def should_mark(ui):
return ui.selected_tool.affects_bg_color
class ToolToggleAffectsXformItem(ToolSettingsItem):
label = " Affects: character xform"
command = "toggle_affects_xform"
def should_mark(ui):
return ui.selected_tool.affects_xform
# cycle between the 3 different fill boundary types
class ToolSetFillBoundariesItem(ArtModePulldownMenuItem):
label = "blah"
command = "cycle_fill_boundary_mode"
def should_dim(app):
return type(app.ui.selected_tool) is not FillTool
def get_label(app):
return "Fill tool bounded by: {}".format(
app.ui.fill_tool.boundary_mode_names[app.ui.fill_tool.boundary_mode]
)
#
# view menu
#
class ViewToggleCRTItem(ArtModePulldownMenuItem):
label = " CRT filter"
command = "toggle_crt"
game_mode_allowed = True
def should_dim(app):
return app.fb.disable_crt
def should_mark(ui):
return ui.app.fb.crt
class ViewToggleGridItem(ArtModePulldownMenuItem):
label = " Grid"
command = "toggle_grid_visibility"
game_mode_allowed = True
def should_mark(ui):
return ui.app.grid.visible
class ViewBGTextureItem(ArtModePulldownMenuItem):
label = " Textured background"
command = "toggle_bg_texture"
always_active = True
def should_mark(ui):
return ui.app.show_bg_texture
class ViewToggleZoomExtentsItem(ArtModePulldownMenuItem):
label = " Zoom to Art extents"
command = "toggle_zoom_extents"
def should_mark(ui):
return ui.active_art and ui.active_art.camera_zoomed_extents
class ViewZoomInItem(ArtModePulldownMenuItem):
label = "Zoom in"
command = "camera_zoom_in_proportional"
class ViewZoomOutItem(ArtModePulldownMenuItem):
label = "Zoom out"
command = "camera_zoom_out_proportional"
class ViewSetZoomItem(ArtModePulldownMenuItem):
label = "Set camera zoom…"
command = "set_camera_zoom"
class ViewToggleCameraTiltItem(ArtModePulldownMenuItem):
label = " Camera tilt"
command = "toggle_camera_tilt"
always_active = True
game_mode_allowed = True
def should_mark(ui):
return ui.app.camera.y_tilt != 0
class ViewSetOverlayImageItem(ArtModePulldownMenuItem):
label = "Set overlay image…"
command = "select_overlay_image"
class ViewToggleOverlayImageItem(ArtModePulldownMenuItem):
label = " Toggle overlay image"
command = "toggle_overlay_image"
def should_mark(ui):
return ui.app.draw_overlay
def should_dim(app):
return app.overlay_renderable is None
class ViewSetOverlayImageOpacityItem(ArtModePulldownMenuItem):
label = "Set overlay image opacity…"
command = "set_overlay_image_opacity"
def should_dim(app):
return app.overlay_renderable is None or not app.draw_overlay
class ViewSetOverlayImageScalingItem(ArtModePulldownMenuItem):
label = "blah"
command = "set_overlay_image_scaling"
def get_label(app):
return "Overlay image scaling: {}".format(
["width", "height", "fill"][app.overlay_scale_type]
)
def should_dim(app):
return app.overlay_renderable is None or not app.draw_overlay
#
# art menu
#
class ArtOpenAllGameAssetsItem(ArtModePulldownMenuItem):
label = "Open all Game Mode assets"
command = "open_all_game_assets"
def should_dim(app):
return len(app.gw.objects) == 0
class ArtPreviousItem(ArtModePulldownMenuItem):
label = "Previous Art"
command = "previous_art"
def should_dim(app):
return len(app.art_loaded_for_edit) < 2
class ArtNextItem(ArtModePulldownMenuItem):
label = "Next Art"
command = "next_art"
def should_dim(app):
return len(app.art_loaded_for_edit) < 2
class ArtCropToSelectionItem(ArtModePulldownMenuItem):
label = "Crop to selection"
command = "crop_to_selection"
def should_dim(app):
return len(app.ui.select_tool.selected_tiles) == 0
class ArtResizeItem(ArtModePulldownMenuItem):
label = "Resize…"
command = "resize_art"
class ArtFlipHorizontal(ArtModePulldownMenuItem):
label = "Flip horizontally"
command = "art_flip_horizontal"
class ArtFlipVertical(ArtModePulldownMenuItem):
label = "Flip vertically"
command = "art_flip_vertical"
class ArtToggleFlipAffectsXforms(ArtModePulldownMenuItem):
label = " Flip affects xforms"
command = "art_toggle_flip_affects_xforms"
def should_mark(ui):
return ui.flip_affects_xforms
class ArtRunScriptItem(ArtModePulldownMenuItem):
label = "Run Artscript…"
command = "run_art_script"
class ArtRunLastScriptItem(ArtModePulldownMenuItem):
label = "Run last Artscript"
command = "run_art_script_last"
def should_dim(app):
return app.last_art_script is None
#
# frame menu
#
class FramePreviousItem(ArtModePulldownMenuItem):
label = "Previous frame"
command = "previous_frame"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.frames < 2
class FrameNextItem(ArtModePulldownMenuItem):
label = "Next frame"
command = "next_frame"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.frames < 2
class FrameTogglePlaybackItem(ArtModePulldownMenuItem):
label = "blah"
command = "toggle_anim_playback"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.frames < 2
def get_label(app):
if not app.ui.active_art:
return "Start animation playback"
animating = app.ui.active_art.renderables[0].animating
return ["Start", "Stop"][animating] + " animation playback"
class FrameToggleOnionItem(ArtModePulldownMenuItem):
label = "blah"
command = "toggle_onion_visibility"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.frames < 2
def get_label(app):
l = "{} onion skin frames".format(["Show", "Hide"][app.onion_frames_visible])
return l
class FrameCycleOnionFramesItem(ArtModePulldownMenuItem):
label = "blah"
command = "cycle_onion_frames"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.frames < 2
def get_label(app):
return "Number of onion frames: {}".format(app.onion_show_frames)
class FrameCycleOnionDisplayItem(ArtModePulldownMenuItem):
label = "blah"
command = "cycle_onion_ahead_behind"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.frames < 2
def get_label(app):
if app.onion_show_frames_behind and app.onion_show_frames_ahead:
display = "Next & Previous"
elif app.onion_show_frames_behind:
display = "Previous"
else:
display = "Next"
return "Onion frames show: {}".format(display)
class FrameAddFrameItem(ArtModePulldownMenuItem):
label = "Add frame…"
command = "add_frame"
class FrameDuplicateFrameItem(ArtModePulldownMenuItem):
label = "Duplicate this frame…"
command = "duplicate_frame"
class FrameChangeDelayItem(ArtModePulldownMenuItem):
label = "Change this frame's hold time…"
command = "change_frame_delay"
class FrameChangeDelayAllItem(ArtModePulldownMenuItem):
label = "Change all frames' hold times…"
command = "change_frame_delay_all"
class FrameChangeIndexItem(ArtModePulldownMenuItem):
label = "Change this frame's index…"
command = "change_frame_index"
class FrameDeleteFrameItem(ArtModePulldownMenuItem):
label = "Delete this frame"
command = "delete_frame"
def should_dim(app):
# don't delete last frame
return not app.ui.active_art or app.ui.active_art.frames < 2
#
# layer menu
#
class LayerAddItem(ArtModePulldownMenuItem):
label = "Add layer…"
command = "add_layer"
class LayerDuplicateItem(ArtModePulldownMenuItem):
label = "Duplicate this layer…"
command = "duplicate_layer"
class LayerSetNameItem(ArtModePulldownMenuItem):
label = "Change this layer's name…"
command = "change_layer_name"
class LayerSetZItem(ArtModePulldownMenuItem):
label = "Change this layer's Z-depth…"
command = "change_layer_z"
class LayerToggleVisibleItem(ArtModePulldownMenuItem):
label = "blah"
command = "toggle_layer_visibility"
def get_label(app):
if not app.ui.active_art:
return "Show this layer (Game Mode)"
visible = app.ui.active_art.layers_visibility[app.ui.active_art.active_layer]
return ["Show", "Hide"][visible] + " this layer (Game Mode)"
class LayerDeleteItem(ArtModePulldownMenuItem):
label = "Delete this layer"
command = "delete_layer"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.layers < 2
class LayerSetInactiveVizItem(ArtModePulldownMenuItem):
label = "blah"
command = "cycle_inactive_layer_visibility"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.layers < 2
def get_label(app):
l = "Inactive layers: "
if app.inactive_layer_visibility == LAYER_VIS_FULL:
return l + "Visible"
elif app.inactive_layer_visibility == LAYER_VIS_DIM:
return l + "Dim"
elif app.inactive_layer_visibility == LAYER_VIS_NONE:
return l + "Invisible"
class LayerShowHiddenItem(ArtModePulldownMenuItem):
label = "blah"
command = "toggle_hidden_layers_visible"
def get_label(app):
l = "Art Mode-only layers: "
l += ["Hidden", "Visible"][app.show_hidden_layers]
return l
class LayerPreviousItem(ArtModePulldownMenuItem):
label = "Previous layer"
command = "previous_layer"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.layers < 2
class LayerNextItem(ArtModePulldownMenuItem):
label = "Next layer"
command = "next_layer"
def should_dim(app):
return not app.ui.active_art or app.ui.active_art.layers < 2
#
# char/color menu
#
class ChooseCharSetItem(ArtModePulldownMenuItem):
label = "Choose character set…"
command = "choose_charset"
class ChoosePaletteItem(ArtModePulldownMenuItem):
label = "Choose palette…"
command = "choose_palette"
class PaletteFromImageItem(ArtModePulldownMenuItem):
label = "Palette from image…"
command = "palette_from_file"
always_active = True
#
# help menu
#
class HelpDocsItem(ArtModePulldownMenuItem):
label = "Help (in browser)"
command = "open_help_docs"
always_active = True
close_on_select = True
game_mode_allowed = True
class HelpGenerateDocsItem(ArtModePulldownMenuItem):
label = "Generate documentation"
command = "generate_docs"
close_on_select = True
def should_dim(app):
return not app.pdoc_available
class HelpWebsiteItem(ArtModePulldownMenuItem):
label = "Playscii website"
command = "open_website"
always_active = True
close_on_select = True
#
# menu data
#
class PulldownMenuData:
"data for pulldown menus, eg File, Edit, etc; mainly a list of menu items"
items = []
def should_mark_item(item, ui):
"returns True if this item should be marked, subclasses have custom logic here"
return False
def get_items(app):
"""
returns a list of items generated from app state, used for
dynamically-generated items
"""
return []
class FileMenuData(PulldownMenuData):
items = [
FileNewItem,
FileOpenItem,
FileSaveItem,
FileSaveAsItem,
FileCloseItem,
FileRevertItem,
SeparatorItem,
FileImportItem,
FileExportItem,
FileExportLastItem,
SeparatorItem,
FileQuitItem,
]
class EditMenuData(PulldownMenuData):
items = [
EditUndoItem,
EditRedoItem,
SeparatorItem,
EditCutItem,
EditCopyItem,
EditPasteItem,
EditDeleteItem,
SeparatorItem,
EditSelectAllItem,
EditSelectNoneItem,
EditSelectInvertItem,
SeparatorItem,
EditPreferences,
]
class ToolMenuData(PulldownMenuData):
items = [
ToolTogglePickerItem,
ToolTogglePickerHoldItem,
ToolSwapSelectedColors,
ToolToggleArtToolbar,
SeparatorItem,
ToolPaintItem,
ToolEraseItem,
ToolRotateItem,
ToolGrabItem,
ToolTextItem,
ToolSelectItem,
ToolPasteItem,
ToolFillItem,
SeparatorItem,
ToolIncreaseBrushSizeItem,
ToolDecreaseBrushSizeItem,
ToolToggleAffectsCharItem,
ToolToggleAffectsFGItem,
ToolToggleAffectsBGItem,
ToolToggleAffectsXformItem,
SeparatorItem,
ToolSetFillBoundariesItem,
]
# TODO: cycle char/color/xform items?
# TODO: generate list from UI.tools instead of manually specified MenuItems
def should_mark_item(item, ui):
# if it's a tool setting toggle, use its own mark check function
if item.__bases__[0] is ToolSettingsItem or hasattr(item, "should_mark"):
return item.should_mark(ui)
return item.label == " {}".format(ui.selected_tool.button_caption)
class ViewMenuData(PulldownMenuData):
items = [
ViewToggleCRTItem,
ViewToggleGridItem,
ViewBGTextureItem,
SeparatorItem,
ViewToggleZoomExtentsItem,
ViewZoomInItem,
ViewZoomOutItem,
ViewSetZoomItem,
ViewToggleCameraTiltItem,
SeparatorItem,
ViewSetOverlayImageItem,
ViewToggleOverlayImageItem,
ViewSetOverlayImageOpacityItem,
ViewSetOverlayImageScalingItem,
]
def should_mark_item(item, ui):
if hasattr(item, "should_mark"):
return item.should_mark(ui)
return False
class ArtMenuData(PulldownMenuData):
items = [
ArtResizeItem,
ArtCropToSelectionItem,
ArtFlipHorizontal,
ArtFlipVertical,
ArtToggleFlipAffectsXforms,
SeparatorItem,
ArtRunScriptItem,
ArtRunLastScriptItem,
SeparatorItem,
ArtOpenAllGameAssetsItem,
SeparatorItem,
ArtPreviousItem,
ArtNextItem,
SeparatorItem,
]
def should_mark_item(item, ui):
"show checkmark for active art"
if hasattr(item, "should_mark"):
return item.should_mark(ui)
return ui.active_art and ui.active_art.filename == item.cb_arg
def get_items(app):
"turn each loaded art into a menu item"
items = []
for art in app.art_loaded_for_edit:
# class just being used to store data, no need to spawn it
class TempMenuItemClass(ArtModePulldownMenuItem):
pass
item = TempMenuItemClass
# leave spaces for mark
item.label = " {}".format(art.filename)
item.command = "art_switch_to"
item.cb_arg = art.filename
# order list by art's time loaded
item.time_loaded = art.time_loaded
items.append(item)
items.sort(key=lambda item: item.time_loaded)
return items
class FrameMenuData(PulldownMenuData):
items = [
FrameAddFrameItem,
FrameDuplicateFrameItem,
FrameChangeDelayItem,
FrameChangeDelayAllItem,
FrameChangeIndexItem,
FrameDeleteFrameItem,
SeparatorItem,
FrameTogglePlaybackItem,
FramePreviousItem,
FrameNextItem,
SeparatorItem,
FrameToggleOnionItem,
FrameCycleOnionFramesItem,
FrameCycleOnionDisplayItem,
]
class LayerMenuData(PulldownMenuData):
items = [
LayerAddItem,
LayerDuplicateItem,
LayerSetNameItem,
LayerSetZItem,
LayerDeleteItem,
SeparatorItem,
LayerSetInactiveVizItem,
LayerPreviousItem,
LayerNextItem,
SeparatorItem,
LayerToggleVisibleItem,
LayerShowHiddenItem,
SeparatorItem,
]
def should_mark_item(item, ui):
"show checkmark for active art"
if not ui.active_art:
return False
return ui.active_art.active_layer == item.cb_arg
def get_items(app):
"turn each layer into a menu item"
items = []
if not app.ui.active_art:
return items
# first determine longest line to set width of items
longest_line = 0
for layer_name in app.ui.active_art.layer_names:
if len(layer_name) > longest_line:
longest_line = len(layer_name)
# check non-generated menu items too
for item in LayerMenuData.items:
if len(item.label) + 1 > longest_line:
longest_line = len(item.label) + 1
# cap at max allowed line length
longest_line = min(longest_line, 50)
for i, layer_name in enumerate(app.ui.active_art.layer_names):
class TempMenuItemClass(ArtModePulldownMenuItem):
pass
item = TempMenuItemClass
# leave spaces for mark
item.label = " {}".format(layer_name)
if not app.ui.active_art.layers_visibility[i]:
item.label += " (hidden)"
# pad, put Z depth on far right
item.label = item.label.ljust(longest_line)
# trim to keep below a max length
item.label = item.label[:longest_line]
# spaces between layer name and z depth
item.label += "z:{:.2f}".format(app.ui.active_art.layers_z[i])
# tell PulldownMenu's button creation process not to auto-pad
item.no_pad = True
item.command = "layer_switch_to"
item.cb_arg = i
items.append(item)
return items
class CharColorMenuData(PulldownMenuData):
items = [ChooseCharSetItem, ChoosePaletteItem, SeparatorItem, PaletteFromImageItem]
class HelpMenuData(PulldownMenuData):
items = [HelpDocsItem, HelpGenerateDocsItem, HelpWebsiteItem]