X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gui%2Fdrawwindow.py;h=f5ba5f9056605c78af029414577683375ea07669;hb=e98eb4660f5e6d4b479ae496c6901e42a1595908;hp=344a453268646a1ac7f02e116b1b5c1bcc72c1ea;hpb=0bf4aebee65c428c4a68e2e5f4883ea482bd1864;p=mypaint-anime%2Fmaster.git diff --git a/gui/drawwindow.py b/gui/drawwindow.py index 344a453..f5ba5f9 100644 --- a/gui/drawwindow.py +++ b/gui/drawwindow.py @@ -13,16 +13,16 @@ This is the main drawing window, containing menu actions. Painting is done in tileddrawwidget.py. """ -MYPAINT_VERSION="0.9.1+git" +MYPAINT_VERSION="1.0.0" -import os, math, time +import os, math, time, webbrowser from gettext import gettext as _ import gtk, gobject from gtk import gdk, keysyms import pango -import colorselectionwindow, historypopup, stategroup, colorpicker, windowing, layout +import colorselectionwindow, historypopup, stategroup, colorpicker, windowing, layout, toolbar import dialogs from lib import helpers import stock @@ -129,11 +129,10 @@ def button_press_cb_abstraction(drawwindow, win, event, doc): return True # Dispatch regular GTK events. - for ag in drawwindow.action_group, doc.action_group: - action = ag.get_action(action_name) - if action is not None: - action.activate() - return True + action = drawwindow.app.find_action(action_name) + if action is not None: + action.activate() + return True def button_release_cb_abstraction(win, event, doc): #print event.device, event.button @@ -182,6 +181,14 @@ class Window (windowing.MainWindow, layout.MainWindow): lm = app.layout_manager layout.MainWindow.__init__(self, lm) + + # Park the focus on the main tdw rather than on the toolbar. Default + # activation doesn't really mean much for MyPaint's main window, so + # it's safe to do this and it looks better. + self.main_widget.set_can_default(True) + self.main_widget.set_can_focus(True) + self.main_widget.grab_focus() + self.main_widget.connect("button-press-event", self.button_press_cb) self.main_widget.connect("button-release-event",self.button_release_cb) self.main_widget.connect("scroll-event", self.scroll_cb) @@ -213,8 +220,10 @@ class Window (windowing.MainWindow, layout.MainWindow): ('ColorMenu', None, _('Color')), ('ColorPickerPopup', gtk.STOCK_COLOR_PICKER, _('Pick Color'), 'r', None, self.popup_cb), ('ColorHistoryPopup', None, _('Color History'), 'x', None, self.popup_cb), - ('ColorChangerPopup', None, _('Color Changer'), 'v', None, self.popup_cb), + ('ColorChangerCrossedBowlPopup', None, _('Color Changer (crossed bowl)'), 'v', None, self.popup_cb), + ('ColorChangerWashPopup', None, _('Color Changer (washed)'), 'c', None, self.popup_cb), ('ColorRingPopup', None, _('Color Ring'), None, None, self.popup_cb), + ('ColorDetailsDialog', None, _("Color Details"), None, None, self.color_details_dialog_cb), ('ContextMenu', None, _('Brushkeys')), ('ContextHelp', gtk.STOCK_HELP, _('Help!'), None, None, self.show_infodialog_cb), @@ -236,7 +245,9 @@ class Window (windowing.MainWindow, layout.MainWindow): ('ScratchCopyBackground', None, _('Copy Background to Scratchpad'), None, None, self.scratchpad_copy_background_cb), ('BrushMenu', None, _('Brush')), - ('ImportBrushPack', gtk.STOCK_OPEN, _('Import brush package...'), '', None, self.import_brush_pack_cb), + ('BrushChooserPopup', stock.TOOL_BRUSH, _("Change Brush..."), 'b', None, self.brush_chooser_popup_cb), + ('DownloadBrushPack', gtk.STOCK_OPEN, _('Download more brushes (in web browser)'), '', None, self.download_brush_pack_cb), + ('ImportBrushPack', gtk.STOCK_OPEN, _('Import brush package...'), '', None, self.import_brush_pack_cb), ('HelpMenu', None, _('Help')), ('Docu', gtk.STOCK_INFO, _('Where is the Documentation?'), None, None, self.show_infodialog_cb), @@ -253,11 +264,13 @@ class Window (windowing.MainWindow, layout.MainWindow): ('ViewMenu', None, _('View')), ('MenuishBarMenu', None, _('Toolbars')), ('ShowPopupMenu', None, _('Popup Menu'), 'Menu', None, self.popupmenu_show_cb), - ('Fullscreen', gtk.STOCK_FULLSCREEN, _('Fullscreen'), 'F11', None, self.fullscreen_cb), + ('Fullscreen', gtk.STOCK_FULLSCREEN, None, 'F11', None, self.fullscreen_cb), ('ViewHelp', gtk.STOCK_HELP, _('Help'), None, None, self.show_infodialog_cb), ] ag = self.action_group = gtk.ActionGroup('WindowActions') + self.app.add_action_group(ag) ag.add_actions(actions) + self.update_fullscreen_action() # Toggle actions toggle_actions = [ @@ -273,10 +286,12 @@ class Window (windowing.MainWindow, layout.MainWindow): ('BackgroundWindow', gtk.STOCK_PAGE_SETUP, _('Background'), None, None, self.toggle_window_cb), ('BrushSelectionWindow', stock.TOOL_BRUSH, - None, None, _("Toggle the Brush selector"), + None, None, + _("Edit and reorganise Brush Lists"), self.toggle_window_cb), ('BrushSettingsWindow', gtk.STOCK_PROPERTIES, - _('Brush Editor'), 'b', None, + _('Brush Settings Editor'), 'b', + _("Change Brush Settings in detail"), self.toggle_window_cb), ('ColorSelectionWindow', stock.TOOL_COLOR_SELECTOR, None, None, _("Toggle the Colour Triangle"), @@ -340,25 +355,31 @@ class Window (windowing.MainWindow, layout.MainWindow): # Keyboard handling for action in self.action_group.list_actions(): self.app.kbm.takeover_action(action) - self.app.ui_manager.insert_action_group(ag, -1) def init_stategroups(self): sg = stategroup.StateGroup() p2s = sg.create_popup_state - changer = p2s(colorselectionwindow.ColorChangerPopup(self.app)) + changer_crossed_bowl = p2s(colorselectionwindow.ColorChangerCrossedBowlPopup(self.app)) + changer_wash = p2s(colorselectionwindow.ColorChangerWashPopup(self.app)) ring = p2s(colorselectionwindow.ColorRingPopup(self.app)) hist = p2s(historypopup.HistoryPopup(self.app, self.app.doc.model)) pick = self.colorpick_state = p2s(colorpicker.ColorPicker(self.app, self.app.doc.model)) self.popup_states = { - 'ColorChangerPopup': changer, + 'ColorChangerCrossedBowlPopup': changer_crossed_bowl, + 'ColorChangerWashPopup': changer_wash, 'ColorRingPopup': ring, 'ColorHistoryPopup': hist, 'ColorPickerPopup': pick, } - changer.next_state = ring - ring.next_state = changer - changer.autoleave_timeout = None + + # not sure how useful this is; we can't cycle at the moment + changer_crossed_bowl.next_state = ring + ring.next_state = changer_wash + changer_wash.next_state = ring + + changer_wash.autoleave_timeout = None + changer_crossed_bowl.autoleave_timeout = None ring.autoleave_timeout = None pick.max_key_hit_duration = 0.0 @@ -379,26 +400,8 @@ class Window (windowing.MainWindow, layout.MainWindow): self.menubar = self.app.ui_manager.get_widget('/Menubar') def init_toolbar(self): - toolbarpath = os.path.join(self.app.datapath, 'gui/toolbar.xml') - toolbarbar_xml = open(toolbarpath).read() - self.app.ui_manager.add_ui_from_string(toolbarbar_xml) - self.toolbar1 = self.app.ui_manager.get_widget('/toolbar1') - self.toolbar1.set_style(gtk.TOOLBAR_ICONS) - self.toolbar1.set_border_width(0) - self.toolbar1.connect("style-set", self.on_toolbar1_style_set) - self.toolbar = gtk.HBox() - self.menu_button = FakeMenuButton(_("MyPaint"), self.popupmenu) - self.menu_button.set_border_width(0) - self.toolbar.pack_start(self.menu_button, False, False) - self.toolbar.pack_start(self.toolbar1, True, True) - self.menu_button.set_flags(gtk.CAN_DEFAULT) - self.set_default(self.menu_button) - - def on_toolbar1_style_set(self, widget, oldstyle): - style = widget.style.copy() - self.menu_button.set_style(style) - style = widget.style.copy() - self.toolbar.set_style(style) + self.toolbar_manager = toolbar.ToolbarManager(self) + self.toolbar = self.toolbar_manager.toolbar1 def _clone_menu(self, xml, name, owner=None): """ @@ -609,6 +612,16 @@ class Window (windowing.MainWindow, layout.MainWindow): state.activate(action) + def brush_chooser_popup_cb(self, action): + # It may be even nicer to do this as a real popup state with + # mouse-out to cancel. The Action is named accordingly. For now + # though a modal dialog will do as an implementation. + dialogs.change_current_brush_quick(self.app) + + def color_details_dialog_cb(self, action): + dialogs.change_current_color_detailed(self.app) + + # User-toggleable UI pieces: things like toolbars, status bars, menu bars. # Saved between sessions. @@ -664,9 +677,9 @@ class Window (windowing.MainWindow, layout.MainWindow): toolbar_visible = self.toolbar.get_property("visible") menubar_visible = self.menubar.get_property("visible") if toolbar_visible and menubar_visible: - self.menu_button.hide() + self.toolbar_manager.menu_button.hide() else: - self.menu_button.show_all() + self.toolbar_manager.menu_button.show_all() def on_menuishbar_radio_change(self, radioaction, current): @@ -755,13 +768,25 @@ class Window (windowing.MainWindow, layout.MainWindow): self.set_show_subwindows(True) del self._restore_subwindows_on_unfullscreen self.update_menu_button() + self.update_fullscreen_action() + + def update_fullscreen_action(self): + action = self.action_group.get_action("Fullscreen") + if self.is_fullscreen: + action.set_stock_id(gtk.STOCK_LEAVE_FULLSCREEN) + action.set_tooltip(_("Leave Fullscreen Mode")) + action.set_label(_("UnFullscreen")) + else: + action.set_stock_id(gtk.STOCK_FULLSCREEN) + action.set_tooltip(_("Enter Fullscreen Mode")) + action.set_label(_("Fullscreen")) def popupmenu_show_cb(self, action): self.show_popupmenu() def show_popupmenu(self, event=None): self.menubar.set_sensitive(False) # excessive feedback? - self.menu_button.set_sensitive(False) + self.toolbar_manager.menu_button.set_sensitive(False) button = 1 time = 0 if event is not None: @@ -783,7 +808,7 @@ class Window (windowing.MainWindow, layout.MainWindow): # the other. Makes it clear that the popups are the same thing as # the full menu, maybe. self.menubar.set_sensitive(True) - self.menu_button.set_sensitive(True) + self.toolbar_manager.menu_button.set_sensitive(True) self.popupmenu_last_active = self.popupmenu.get_active() # BEGIN -- Scratchpad menu options @@ -889,6 +914,11 @@ class Window (windowing.MainWindow, layout.MainWindow): enabled = self.app.doc.model.frame_enabled self.app.doc.model.set_frame_enabled(not enabled) + def download_brush_pack_cb(self, *junk): + url = 'http://wiki.mypaint.info/index.php?title=Brush_Packages/redirect_mypaint_1.0_gui' + print 'URL:', url + webbrowser.open(url) + def import_brush_pack_cb(self, *junk): format_id, filename = dialogs.open_dialog(_("Import brush package..."), self, [(_("MyPaint brush package (*.zip)"), "*.zip")]) @@ -932,6 +962,8 @@ class Window (windowing.MainWindow, layout.MainWindow): u'David Grundberg (%s)' % _('programming'), u"Krzysztof Pasek (%s)" % _('programming'), u"Ben O'Steen (%s)" % _('programming'), + u"Ferry Jérémie (%s)" % _('programming'), + u"しげっち 'sigetch' (%s)" % _('programming'), ]) d.set_artists([ u"Artis Rozentāls (%s)" % _('brushes'), @@ -1006,106 +1038,3 @@ class Window (windowing.MainWindow, layout.MainWindow): self.app.message_dialog(text[action.get_name()]) -class FakeMenuButton(gtk.EventBox): - """Launches the popup menu when clicked. - - One of these sits to the left of the real toolbar when the main menu bar is - hidden. In addition to providing access to a popup menu associated with the - main view, this is a little more compliant with Fitts's Law than a normal - `gtk.MenuBar`: when the window is fullscreened with only the "toolbar" - present the ``(0, 0)`` screen pixel hits this button. Support note: Compiz - edge bindings sometimes get in the way of this, so turn those off if you - want Fitts's compliance. - """ - - def __init__(self, text, menu): - gtk.EventBox.__init__(self) - self.menu = menu - self.label = gtk.Label(text) - self.label.set_padding(8, 0) - - # Text settings - #self.label.set_angle(5) - attrs = pango.AttrList() - attrs.change(pango.AttrWeight(pango.WEIGHT_HEAVY, 0, -1)) - self.label.set_attributes(attrs) - - # Intercept mouse clicks and use them for activating the togglebutton - # even if they're in its border, or (0, 0). Fitts would approve. - invis = self.invis_window = gtk.EventBox() - invis.set_visible_window(False) - invis.set_above_child(True) - invis.connect("button-press-event", self.on_button_press) - invis.connect("enter-notify-event", self.on_enter) - invis.connect("leave-notify-event", self.on_leave) - - # The underlying togglebutton can default and focus. Might as well make - # the Return key do something useful rather than invoking the 1st - # toolbar item. - self.togglebutton = gtk.ToggleButton() - self.togglebutton.add(self.label) - self.togglebutton.set_relief(gtk.RELIEF_HALF) - self.togglebutton.set_flags(gtk.CAN_FOCUS) - self.togglebutton.set_flags(gtk.CAN_DEFAULT) - self.togglebutton.connect("toggled", self.on_togglebutton_toggled) - - invis.add(self.togglebutton) - self.add(invis) - for sig in "selection-done", "deactivate", "cancel": - menu.connect(sig, self.on_menu_dismiss) - - - def on_enter(self, widget, event): - # Not this set_state(). That one. - #self.togglebutton.set_state(gtk.STATE_PRELIGHT) - gtk.Widget.set_state(self.togglebutton, gtk.STATE_PRELIGHT) - - - def on_leave(self, widget, event): - #self.togglebutton.set_state(gtk.STATE_NORMAL) - gtk.Widget.set_state(self.togglebutton, gtk.STATE_NORMAL) - - - def on_button_press(self, widget, event): - # Post the menu. Menu operation is much more convincing if we call - # popup() with event details here rather than leaving it to the toggled - # handler. - pos_func = self._get_popup_menu_position - self.menu.popup(None, None, pos_func, event.button, event.time) - self.togglebutton.set_active(True) - - - def on_togglebutton_toggled(self, togglebutton): - # Post the menu from a keypress. Dismiss handler untoggles it. - if togglebutton.get_active(): - if not self.menu.get_property("visible"): - pos_func = self._get_popup_menu_position - self.menu.popup(None, None, pos_func, 1, 0) - - - def on_menu_dismiss(self, *a, **kw): - # Reset the button state when the user's finished, and - # park focus back on the menu button. - self.set_state(gtk.STATE_NORMAL) - self.togglebutton.set_active(False) - self.togglebutton.grab_focus() - - - def _get_popup_menu_position(self, menu, *junk): - # Underneath the button, at the same x position. - x, y = self.window.get_origin() - y += self.allocation.height - return x, y, True - - - def set_style(self, style): - # Propagate style changes to all children as well. Since this button is - # stored on the toolbar, the main window makes it share a style with - # it. Looks prettier. - gtk.EventBox.set_style(self, style) - style = style.copy() - widget = self.togglebutton - widget.set_style(style) - style = style.copy() - widget = widget.get_child() - widget.set_style(style)