This is an automated email from the git hooks/post-receive script. thansen pushed a commit to branch master in repository aseprite.
commit 2d64a1926e6119d6c38a7d12fdc2fb6bed82b640 Author: David Capello <[email protected]> Date: Tue Dec 15 17:12:11 2015 -0300 Improve BrushPopup to save custom brushes (type/size/angle params) We moved custom brushes stuff from ContextBar to app::AppBrushes class. And now we can access the list of brushes from app::App::brushes() member. --- src/app/CMakeLists.txt | 1 + src/app/app.h | 3 + src/app/app_brushes.cpp | 117 +++++++++++++ src/app/app_brushes.h | 78 +++++++++ src/app/commands/cmd_keyboard_shortcuts.cpp | 24 ++- src/app/commands/cmd_new_brush.cpp | 3 +- src/app/ui/brush_popup.cpp | 256 ++++++++++++++++++---------- src/app/ui/brush_popup.h | 27 ++- src/app/ui/button_set.cpp | 30 +++- src/app/ui/button_set.h | 5 +- src/app/ui/context_bar.cpp | 146 ++++++---------- src/app/ui/context_bar.h | 30 +--- 12 files changed, 480 insertions(+), 240 deletions(-) diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 490c21c..275655b 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -90,6 +90,7 @@ endif() add_library(app-lib app.cpp + app_brushes.cpp app_menus.cpp app_options.cpp app_render.cpp diff --git a/src/app/app.h b/src/app/app.h index 3c1e7bc..ba1ae1c 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -9,6 +9,7 @@ #define APP_APP_H_INCLUDED #pragma once +#include "app/app_brushes.h" #include "base/signal.h" #include "base/string.h" #include "base/unique_ptr.h" @@ -69,6 +70,7 @@ namespace app { RecentFiles* getRecentFiles() const; MainWindow* getMainWindow() const { return m_mainWindow; } Preferences& preferences() const; + AppBrushes& brushes() { return m_brushes; } void showNotification(INotificationDelegate* del); void updateDisplayTitleBar(); @@ -95,6 +97,7 @@ namespace app { base::UniquePtr<MainWindow> m_mainWindow; FileList m_files; base::UniquePtr<DocumentExporter> m_exporter; + AppBrushes m_brushes; }; void app_refresh_screen(); diff --git a/src/app/app_brushes.cpp b/src/app/app_brushes.cpp new file mode 100644 index 0000000..a3a2add --- /dev/null +++ b/src/app/app_brushes.cpp @@ -0,0 +1,117 @@ +// Aseprite +// Copyright (C) 2001-2015 David Capello +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/app_brushes.h" + +namespace app { + +using namespace doc; + +AppBrushes::AppBrushes() +{ + m_standard.push_back(BrushRef(new Brush(kCircleBrushType, 7, 0))); + m_standard.push_back(BrushRef(new Brush(kSquareBrushType, 7, 0))); + m_standard.push_back(BrushRef(new Brush(kLineBrushType, 7, 44))); +} + +AppBrushes::slot_id AppBrushes::addCustomBrush(const BrushRef& brush) +{ + // Use an empty slot + for (size_t i=0; i<m_slots.size(); ++i) { + if (!m_slots[i].locked() || + !m_slots[i].brush()) { + m_slots[i].setBrush(brush); + return i+1; + } + } + + m_slots.push_back(BrushSlot(brush)); + ItemsChange(); + return (int)m_slots.size(); // Returns the slot +} + +void AppBrushes::removeCustomBrush(slot_id slot) +{ + --slot; + if (slot >= 0 && slot < (int)m_slots.size()) { + m_slots[slot].setBrush(BrushRef(nullptr)); + + // Erase empty trailing slots + while (!m_slots.empty() && + !m_slots[m_slots.size()-1].brush()) + m_slots.erase(--m_slots.end()); + + ItemsChange(); + } +} + +void AppBrushes::removeAllCustomBrushes() +{ + while (!m_slots.empty()) + m_slots.erase(--m_slots.end()); + + ItemsChange(); +} + +bool AppBrushes::hasCustomBrush(slot_id slot) const +{ + --slot; + return (slot >= 0 && slot < (int)m_slots.size() && + m_slots[slot].brush()); +} + +BrushRef AppBrushes::getCustomBrush(slot_id slot) const +{ + --slot; + if (slot >= 0 && slot < (int)m_slots.size()) + return m_slots[slot].brush(); + else + return BrushRef(); +} + +Brushes AppBrushes::getCustomBrushes() +{ + Brushes brushes; + for (const auto& slot : m_slots) + brushes.push_back(slot.brush()); + return brushes; +} + +void AppBrushes::lockCustomBrush(slot_id slot) +{ + --slot; + if (slot >= 0 && slot < (int)m_slots.size() && + m_slots[slot].brush()) { + m_slots[slot].setLocked(true); + } +} + +void AppBrushes::unlockCustomBrush(slot_id slot) +{ + --slot; + if (slot >= 0 && slot < (int)m_slots.size() && + m_slots[slot].brush()) { + m_slots[slot].setLocked(false); + } +} + +bool AppBrushes::isCustomBrushLocked(slot_id slot) const +{ + --slot; + if (slot >= 0 && slot < (int)m_slots.size() && + m_slots[slot].brush()) { + return m_slots[slot].locked(); + } + else + return false; +} + +} // namespace app diff --git a/src/app/app_brushes.h b/src/app/app_brushes.h new file mode 100644 index 0000000..12662ed --- /dev/null +++ b/src/app/app_brushes.h @@ -0,0 +1,78 @@ +// Aseprite +// Copyright (C) 2001-2015 David Capello +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. + +#ifndef APP_APP_BRUSHES_H_INCLUDED +#define APP_APP_BRUSHES_H_INCLUDED +#pragma once + +#include "base/signal.h" +#include "doc/brush.h" +#include "doc/brushes.h" + +#include <vector> + +namespace app { + + class AppBrushes { + public: + // Number of slot (a range from 1 to AppBrushes::size() inclusive) + typedef int slot_id; + + AppBrushes(); + + // Adds a new brush and returns the slot number where the brush + // is now available. + slot_id addCustomBrush(const doc::BrushRef& brush); + void removeCustomBrush(slot_id slot); + void removeAllCustomBrushes(); + bool hasCustomBrush(slot_id slot) const; + const doc::Brushes& getStandardBrushes() { return m_standard; } + doc::BrushRef getCustomBrush(slot_id slot) const; + doc::Brushes getCustomBrushes(); + + void lockCustomBrush(slot_id slot); + void unlockCustomBrush(slot_id slot); + bool isCustomBrushLocked(slot_id slot) const; + + base::Signal0<void> ItemsChange; + + private: + // Custom brush slot + class BrushSlot { + public: + BrushSlot(const doc::BrushRef& brush) + : m_locked(false) + , m_brush(brush) { + } + + // True if this is a standard brush. + bool standard() const { return m_standard; } + + // True if the user locked the brush using the shortcut key to + // access it. + bool locked() const { return m_locked; } + void setLocked(bool locked) { m_locked = locked; } + + // Can be null if the user deletes the brush. + doc::BrushRef brush() const { return m_brush; } + void setBrush(const doc::BrushRef& brush) { m_brush = brush; } + + private: + bool m_standard; + bool m_locked; + doc::BrushRef m_brush; + }; + + typedef std::vector<BrushSlot> BrushSlots; + + doc::Brushes m_standard; + BrushSlots m_slots; + }; + +} // namespace app + +#endif diff --git a/src/app/commands/cmd_keyboard_shortcuts.cpp b/src/app/commands/cmd_keyboard_shortcuts.cpp index e2ffa79..acd25cd 100644 --- a/src/app/commands/cmd_keyboard_shortcuts.cpp +++ b/src/app/commands/cmd_keyboard_shortcuts.cpp @@ -287,7 +287,8 @@ private: class KeyboardShortcutsWindow : public app::gen::KeyboardShortcuts { public: - KeyboardShortcutsWindow() : m_searchChange(false) { + KeyboardShortcutsWindow(const std::string& searchText) + : m_searchChange(false) { setAutoRemap(false); section()->addChild(new ListItem("Menus")); @@ -302,6 +303,11 @@ public: resetButton()->Click.connect(base::Bind<void>(&KeyboardShortcutsWindow::onReset, this)); fillAllLists(); + + if (!searchText.empty()) { + search()->setText(searchText); + onSearchChange(); + } } void restoreKeys() { @@ -523,7 +529,11 @@ public: Command* clone() const override { return new KeyboardShortcutsCommand(*this); } protected: + void onLoadParams(const Params& params) override; void onExecute(Context* context) override; + +private: + std::string m_search; }; KeyboardShortcutsCommand::KeyboardShortcutsCommand() @@ -533,9 +543,19 @@ KeyboardShortcutsCommand::KeyboardShortcutsCommand() { } +void KeyboardShortcutsCommand::onLoadParams(const Params& params) +{ + m_search = params.get("search"); +} + void KeyboardShortcutsCommand::onExecute(Context* context) { - KeyboardShortcutsWindow window; + // Here we copy the m_search field because + // KeyboardShortcutsWindow::fillAllLists() modifies this same + // KeyboardShortcutsCommand instance (so m_search will be "") + // TODO Seeing this, we need a complete new way to handle UI commands execution + std::string neededSearchCopy = m_search; + KeyboardShortcutsWindow window(neededSearchCopy); window.setBounds(gfx::Rect(0, 0, ui::display_w()*3/4, ui::display_h()*3/4)); g_sep = window.bounds().w / 2; diff --git a/src/app/commands/cmd_new_brush.cpp b/src/app/commands/cmd_new_brush.cpp index aa7b71a..d082d0a 100644 --- a/src/app/commands/cmd_new_brush.cpp +++ b/src/app/commands/cmd_new_brush.cpp @@ -149,9 +149,8 @@ void NewBrushCommand::createBrush(const Site& site, const Mask* mask) brush->setImage(image.get()); brush->setPatternOrigin(mask->bounds().origin()); - // TODO add a active stock property in app::Context ContextBar* ctxBar = App::instance()->getMainWindow()->getContextBar(); - int slot = ctxBar->addBrush(brush); + auto slot = App::instance()->brushes().addCustomBrush(brush); ctxBar->setActiveBrush(brush); // Get the shortcut for this brush and show it to the user diff --git a/src/app/ui/brush_popup.cpp b/src/app/ui/brush_popup.cpp index 238f060..42d7e3c 100644 --- a/src/app/ui/brush_popup.cpp +++ b/src/app/ui/brush_popup.cpp @@ -11,12 +11,18 @@ #include "app/ui/brush_popup.h" +#include "app/app.h" +#include "app/app_brushes.h" +#include "app/commands/command.h" #include "app/commands/commands.h" +#include "app/modules/gui.h" #include "app/modules/palettes.h" #include "app/ui/app_menuitem.h" #include "app/ui/button_set.h" +#include "app/ui/context_bar.h" #include "app/ui/keyboard_shortcuts.h" #include "app/ui/skin/skin_theme.h" +#include "app/ui_context.h" #include "base/bind.h" #include "base/convert_to.h" #include "doc/brush.h" @@ -28,10 +34,12 @@ #include "she/scoped_surface_lock.h" #include "she/surface.h" #include "she/system.h" +#include "ui/button.h" +#include "ui/link_label.h" +#include "ui/listitem.h" #include "ui/menu.h" #include "ui/message.h" #include "ui/separator.h" -#include "ui/tooltips.h" namespace app { @@ -41,11 +49,10 @@ using namespace ui; namespace { -class Item : public ButtonSet::Item { +class SelectBrushItem : public ButtonSet::Item { public: - Item(BrushPopup* popup, BrushPopupDelegate* delegate, const BrushRef& brush, int slot = -1) - : m_popup(popup) - , m_delegate(delegate) + SelectBrushItem(BrushPopupDelegate* delegate, const BrushRef& brush, int slot = -1) + : m_delegate(delegate) , m_brush(brush) , m_slot(slot) { SkinPartPtr icon(new SkinPart); @@ -57,35 +64,84 @@ public: return m_brush; } -protected: - bool onProcessMessage(Message* msg) override { - if (msg->type() == kMouseUpMessage && m_slot > 0) { - MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg); - if (mouseMsg->buttons() == kButtonRight) { - Menu menu; - AppMenuItem lockItem(m_delegate->onIsBrushSlotLocked(m_slot) ? "Unlock Brush": "Lock Brush"); - AppMenuItem deleteItem("Delete"); - AppMenuItem deleteAllItem("Delete All"); - lockItem.Click.connect(&Item::onLockBrush, this); - deleteItem.Click.connect(&Item::onDeleteBrush, this); - deleteAllItem.Click.connect(&Item::onDeleteAllBrushes, this); - menu.addChild(&lockItem); - menu.addChild(&deleteItem); - menu.addChild(new MenuSeparator); - menu.addChild(&deleteAllItem); - - // Here we make the popup window temporaly floating, so it's - // not closed by the popup menu. - m_popup->makeFloating(); - menu.showPopup(mouseMsg->position()); - m_popup->makeFixed(); - m_popup->closeWindow(nullptr); - } +private: + + void onClick() override { + if (m_slot >= 0) + m_delegate->onSelectBrushSlot(m_slot); + else + m_delegate->onSelectBrush(m_brush); + } + +private: + + BrushPopupDelegate* m_delegate; + BrushRef m_brush; + int m_slot; +}; + +class BrushShortcutItem : public ButtonSet::Item { +public: + BrushShortcutItem(const std::string& text, int slot) + : m_slot(slot) { + setText(text); + } + +private: + void onClick() override { + Params params; + params.set("change", "custom"); + params.set("slot", base::convert_to<std::string>(m_slot).c_str()); + Command* cmd = CommandsModule::instance()->getCommandByName(CommandId::ChangeBrush); + cmd->loadParams(params); + std::string search = cmd->friendlyName(); + if (!search.empty()) { + params.clear(); + params.set("search", search.c_str()); + cmd = CommandsModule::instance()->getCommandByName(CommandId::KeyboardShortcuts); + ASSERT(cmd); + if (cmd) + UIContext::instance()->executeCommand(cmd, params); } - return ButtonSet::Item::onProcessMessage(msg); + } + + int m_slot; +}; + +class BrushOptionsItem : public ButtonSet::Item { +public: + BrushOptionsItem(BrushPopup* popup, BrushPopupDelegate* delegate, int slot) + : m_popup(popup) + , m_delegate(delegate) + , m_slot(slot) { + setIcon(SkinTheme::instance()->parts.iconArrowDown(), true); } private: + + void onClick() override { + Menu menu; + AppMenuItem lockItem(m_delegate->onIsBrushSlotLocked(m_slot) ? "Unlock Brush": "Lock Brush"); + AppMenuItem deleteItem("Delete"); + AppMenuItem deleteAllItem("Delete All"); + lockItem.Click.connect(&BrushOptionsItem::onLockBrush, this); + deleteItem.Click.connect(&BrushOptionsItem::onDeleteBrush, this); + deleteAllItem.Click.connect(&BrushOptionsItem::onDeleteAllBrushes, this); + menu.addChild(&lockItem); + menu.addChild(&deleteItem); + menu.addChild(new MenuSeparator); + menu.addChild(&deleteAllItem); + + // Here we make the popup window temporaly floating, so it's + // not closed by the popup menu. + m_popup->makeFloating(); + menu.showPopup(gfx::Point(origin().x, origin().y+bounds().h)); + m_popup->makeFixed(); + m_popup->closeWindow(nullptr); + } + +private: + void onLockBrush() { if (m_delegate->onIsBrushSlotLocked(m_slot)) m_delegate->onUnlockBrushSlot(m_slot); @@ -107,98 +163,122 @@ private: int m_slot; }; -} // anonymous namespace +class NewCustomBrushItem : public ButtonSet::Item { +public: + NewCustomBrushItem() { + setText("Save Brush"); + } -static BrushRef defBrushes[3]; +private: + void onClick() override { + AppBrushes& brushes = App::instance()->brushes(); + auto slot = brushes.addCustomBrush( + ContextBar::createBrushFromPreferences()); + brushes.lockCustomBrush(slot); + } +}; + +} // anonymous namespace BrushPopup::BrushPopup(BrushPopupDelegate* delegate) : PopupWindow("", ClickBehavior::CloseOnClickInOtherWindow) + , m_tooltipManager(nullptr) + , m_standardBrushes(3) + , m_customBrushes(nullptr) , m_delegate(delegate) { setAutoRemap(false); - setBorder(gfx::Border(0)); + setBorder(gfx::Border(2)*guiscale()); setChildSpacing(0); + m_box.noBorderNoChildSpacing(); + + addChild(&m_box); + + HBox* top = new HBox; + top->addChild(&m_standardBrushes); + top->addChild(new BoxFiller); + + m_box.addChild(top); + m_box.addChild(new Separator("", HORIZONTAL)); + + const doc::Brushes& brushes = App::instance()->brushes().getStandardBrushes(); + for (const auto& brush : brushes) + m_standardBrushes.addItem(new SelectBrushItem(m_delegate, brush)); + + m_standardBrushes.setTransparent(true); + m_standardBrushes.setBgColor(gfx::ColorNone); + + App::instance()->brushes() + .ItemsChange.connect(&BrushPopup::onBrushChanges, this); } void BrushPopup::setBrush(Brush* brush) { - for (auto child : m_buttons->children()) { - Item* item = static_cast<Item*>(child); + for (auto child : m_standardBrushes.children()) { + SelectBrushItem* item = static_cast<SelectBrushItem*>(child); // Same type and same image if (item->brush() && item->brush()->type() == brush->type() && (brush->type() != kImageBrushType || item->brush()->image() == brush->image())) { - m_buttons->setSelectedItem(item); - break; + m_standardBrushes.setSelectedItem(item); + return; } } } -void BrushPopup::regenerate(const gfx::Rect& box, const Brushes& brushes) +void BrushPopup::regenerate(const gfx::Rect& box) { - int columns = 3; - - if (m_buttons) { - for (auto child : m_buttons->children()) - m_tooltipManager->removeTooltipFor(child); - removeChild(m_buttons.get()); - m_buttons.reset(); + const doc::Brushes& brushes = App::instance()->brushes().getCustomBrushes(); + + if (m_customBrushes) { + // As BrushPopup::regenerate() can be called when a + // "m_customBrushes" button is clicked we cannot delete + // "m_customBrushes" right now. + m_customBrushes->parent()->removeChild(m_customBrushes); + m_customBrushes->deferDelete(); } - if (!defBrushes[0]) { - defBrushes[0].reset(new Brush(kCircleBrushType, 7, 0)); - defBrushes[1].reset(new Brush(kSquareBrushType, 7, 0)); - defBrushes[2].reset(new Brush(kLineBrushType, 7, 44)); - } - - m_buttons.reset(new ButtonSet(columns)); - m_buttons->addItem(new Item(this, m_delegate, defBrushes[0])); - m_buttons->addItem(new Item(this, m_delegate, defBrushes[1])); - m_buttons->addItem(new Item(this, m_delegate, defBrushes[2])); + m_customBrushes = new ButtonSet(3); + m_customBrushes->setTriggerOnMouseUp(true); - int slot = 1; + auto& parts = SkinTheme::instance()->parts; + int slot = 0; for (const auto& brush : brushes) { - Item* item = new Item(this, m_delegate, brush, slot); - m_buttons->addItem(item); - - Params params; - params.set("change", "custom"); - params.set("slot", base::convert_to<std::string>(slot).c_str()); - Key* key = KeyboardShortcuts::instance()->command( - CommandId::ChangeBrush, params); - if (key && !key->accels().empty()) { - std::string tooltip; - tooltip += "Shortcut: "; - tooltip += key->accels().front().toString(); - m_tooltipManager->addTooltipFor(item, tooltip, TOP); + ++slot; + + // Get shortcut + std::string shortcut; + { + Params params; + params.set("change", "custom"); + params.set("slot", base::convert_to<std::string>(slot).c_str()); + Key* key = KeyboardShortcuts::instance()->command( + CommandId::ChangeBrush, params); + if (key && !key->accels().empty()) + shortcut = key->accels().front().toString(); } - slot++; + m_customBrushes->addItem(new SelectBrushItem(m_delegate, brush, slot)); + m_customBrushes->addItem(new BrushShortcutItem(shortcut, slot)); + m_customBrushes->addItem(new BrushOptionsItem(this, m_delegate, slot)); } - // Add empty spaces - while (((slot-1) % columns) > 0) - m_buttons->addItem(new Item(this, m_delegate, BrushRef(nullptr), slot++)); - - m_buttons->ItemChange.connect(base::Bind<void>(&BrushPopup::onButtonChange, this)); - m_buttons->setTransparent(true); - m_buttons->setBgColor(gfx::ColorNone); - addChild(m_buttons.get()); - gfx::Rect rc = box; - int buttons = m_buttons->children().size(); - int rows = (buttons/columns + ((buttons%columns) > 0 ? 1: 0)); - rc.w *= columns; - rc.h = rows * (rc.h-2*guiscale()) + 2*guiscale(); + m_customBrushes->addItem(new NewCustomBrushItem, 3, 1); + m_customBrushes->setExpansive(true); + m_box.addChild(m_customBrushes); - setBounds(rc); + // Resize the window and change the hot region. + setBounds(gfx::Rect(box.origin(), sizeHint())); + setHotRegion(gfx::Region(bounds())); } -void BrushPopup::onButtonChange() +void BrushPopup::onBrushChanges() { - Item* item = static_cast<Item*>(m_buttons->getItem(m_buttons->selectedItem())); - if (item->brush()) - BrushChange(item->brush()); + if (isVisible()) { + regenerate(bounds()); + invalidate(); + } } // static diff --git a/src/app/ui/brush_popup.h b/src/app/ui/brush_popup.h index ccd1c27..00f2cad 100644 --- a/src/app/ui/brush_popup.h +++ b/src/app/ui/brush_popup.h @@ -9,26 +9,20 @@ #define APP_UI_BRUSH_POPUP_H_INCLUDED #pragma once +#include "app/ui/button_set.h" #include "base/shared_ptr.h" -#include "base/signal.h" #include "doc/brushes.h" +#include "ui/box.h" #include "ui/popup_window.h" - -namespace doc { - class Brush; -} - -namespace ui { - class Menu; - class TooltipManager; -} +#include "ui/tooltips.h" namespace app { - class ButtonSet; class BrushPopupDelegate { public: virtual ~BrushPopupDelegate() { } + virtual void onSelectBrush(const doc::BrushRef& brush) = 0; + virtual void onSelectBrushSlot(int slot) = 0; virtual void onDeleteBrushSlot(int slot) = 0; virtual void onDeleteAllBrushes() = 0; virtual bool onIsBrushSlotLocked(int slot) const = 0; @@ -41,21 +35,22 @@ namespace app { BrushPopup(BrushPopupDelegate* delegate); void setBrush(doc::Brush* brush); - void regenerate(const gfx::Rect& box, const doc::Brushes& brushes); + void regenerate(const gfx::Rect& box); void setupTooltips(ui::TooltipManager* tooltipManager) { m_tooltipManager = tooltipManager; } - base::Signal1<void, const doc::BrushRef&> BrushChange; - static she::Surface* createSurfaceForBrush(const doc::BrushRef& brush); private: - void onButtonChange(); + void onStandardBrush(); + void onBrushChanges(); - base::SharedPtr<ButtonSet> m_buttons; ui::TooltipManager* m_tooltipManager; + ui::VBox m_box; + ButtonSet m_standardBrushes; + ButtonSet* m_customBrushes; BrushPopupDelegate* m_delegate; }; diff --git a/src/app/ui/button_set.cpp b/src/app/ui/button_set.cpp index 910802c..60d7277 100644 --- a/src/app/ui/button_set.cpp +++ b/src/app/ui/button_set.cpp @@ -50,9 +50,10 @@ ButtonSet::Item::Item() setFocusStop(true); } -void ButtonSet::Item::setIcon(const SkinPartPtr& icon) +void ButtonSet::Item::setIcon(const SkinPartPtr& icon, bool mono) { m_icon = icon; + m_mono = mono; invalidate(); } @@ -123,11 +124,16 @@ void ButtonSet::Item::onPaint(ui::PaintEvent& ev) theme->drawRect(g, rc, nw.get(), bg); if (m_icon) { + she::Surface* bmp = m_icon->bitmap(0); + if (isSelected() && hasCapture()) - g->drawColoredRgbaSurface(m_icon->bitmap(0), theme->colors.buttonSelectedText(), + g->drawColoredRgbaSurface(bmp, theme->colors.buttonSelectedText(), + iconRc.x, iconRc.y); + else if (m_mono) + g->drawColoredRgbaSurface(bmp, theme->colors.buttonNormalText(), iconRc.x, iconRc.y); else - g->drawRgbaSurface(m_icon->bitmap(0), iconRc.x, iconRc.y); + g->drawRgbaSurface(bmp, iconRc.x, iconRc.y); } if (hasText()) { @@ -160,7 +166,7 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg) if (mnemonicPressed || (hasFocus() && keymsg->scancode() == kKeySpace)) { buttonSet()->setSelectedItem(this); - buttonSet()->onItemChange(this); + onClick(); } } break; @@ -172,7 +178,7 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg) if (static_cast<MouseMessage*>(msg)->left() && !buttonSet()->m_triggerOnMouseUp) { - buttonSet()->onItemChange(this); + onClick(); } break; @@ -183,10 +189,10 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg) if (static_cast<MouseMessage*>(msg)->left()) { if (buttonSet()->m_triggerOnMouseUp) - buttonSet()->onItemChange(this); + onClick(); } else if (static_cast<MouseMessage*>(msg)->right()) { - buttonSet()->onRightClick(this); + onRightClick(); } } break; @@ -232,6 +238,16 @@ void ButtonSet::Item::onSizeHint(ui::SizeHintEvent& ev) ev.setSizeHint(sz); } +void ButtonSet::Item::onClick() +{ + buttonSet()->onItemChange(this); +} + +void ButtonSet::Item::onRightClick() +{ + buttonSet()->onRightClick(this); +} + ButtonSet::ButtonSet(int columns) : Grid(columns, false) , m_offerCapture(true) diff --git a/src/app/ui/button_set.h b/src/app/ui/button_set.h index 968551e..40f7153 100644 --- a/src/app/ui/button_set.h +++ b/src/app/ui/button_set.h @@ -22,15 +22,18 @@ namespace app { class Item : public ui::Widget { public: Item(); - void setIcon(const skin::SkinPartPtr& icon); + void setIcon(const skin::SkinPartPtr& icon, bool mono = false); skin::SkinPartPtr icon() const { return m_icon; } ButtonSet* buttonSet(); protected: void onPaint(ui::PaintEvent& ev) override; bool onProcessMessage(ui::Message* msg) override; void onSizeHint(ui::SizeHintEvent& ev) override; + virtual void onClick(); + virtual void onRightClick(); private: skin::SkinPartPtr m_icon; + bool m_mono; }; ButtonSet(int columns); diff --git a/src/app/ui/context_bar.cpp b/src/app/ui/context_bar.cpp index 7e89e30..56807f6 100644 --- a/src/app/ui/context_bar.cpp +++ b/src/app/ui/context_bar.cpp @@ -12,6 +12,7 @@ #include "app/ui/context_bar.h" #include "app/app.h" +#include "app/app_brushes.h" #include "app/app_menus.h" #include "app/color_utils.h" #include "app/commands/commands.h" @@ -77,13 +78,13 @@ public: BrushTypeField(ContextBar* owner) : ButtonSet(1) , m_owner(owner) + , m_brushes(App::instance()->brushes()) , m_popupWindow(this) { SkinPartPtr part(new SkinPart); part->setBitmap( 0, BrushPopup::createSurfaceForBrush(BrushRef(nullptr))); addItem(part); - m_popupWindow.BrushChange.connect(&BrushTypeField::onBrushChange, this); } ~BrushTypeField() { @@ -103,6 +104,10 @@ public: m_popupWindow.setupTooltips(tooltipManager); } + void showPopupAndHighlightSlot(int slot) { + openPopup(); + } + protected: void onItemChange(Item* item) override { ButtonSet::onItemChange(item); @@ -118,24 +123,55 @@ protected: } // BrushPopupDelegate impl + void onSelectBrush(const BrushRef& brush) { + if (brush->type() == kImageBrushType) + m_owner->setActiveBrush(brush); + else { + Tool* tool = App::instance()->activeTool(); + ToolPreferences::Brush& brushPref = Preferences::instance().tool(tool).brush; + + brushPref.type(static_cast<app::gen::BrushType>(brush->type())); + + m_owner->setActiveBrush( + ContextBar::createBrushFromPreferences(&brushPref)); + } + } + + void onSelectBrushSlot(int slot) { + doc::BrushRef brush = App::instance()->brushes().getCustomBrush(slot); + + // Is this an empty custom brush slot? + if (!brush) + return; + + Tool* tool = App::instance()->activeTool(); + ToolPreferences::Brush& brushPref = Preferences::instance().tool(tool).brush; + + brushPref.type(static_cast<app::gen::BrushType>(brush->type())); + brushPref.size(brush->size()); + brushPref.angle(brush->angle()); + + m_owner->setActiveBrush(brush); + } + void onDeleteBrushSlot(int slot) override { - m_owner->removeBrush(slot); + m_brushes.removeCustomBrush(slot); } void onDeleteAllBrushes() override { - m_owner->removeAllBrushes(); + m_brushes.removeAllCustomBrushes(); } bool onIsBrushSlotLocked(int slot) const override { - return m_owner->isBrushSlotLocked(slot); + return m_brushes.isCustomBrushLocked(slot); } void onLockBrushSlot(int slot) override { - m_owner->lockBrushSlot(slot); + m_brushes.lockCustomBrush(slot); } void onUnlockBrushSlot(int slot) override { - m_owner->unlockBrushSlot(slot); + m_brushes.unlockCustomBrush(slot); } private: @@ -151,7 +187,7 @@ private: void openPopup() { doc::BrushRef brush = m_owner->activeBrush(); - m_popupWindow.regenerate(getPopupBox(), m_owner->getBrushes()); + m_popupWindow.regenerate(getPopupBox()); m_popupWindow.setBrush(brush.get()); Region rgn(m_popupWindow.bounds().createUnion(bounds())); @@ -165,21 +201,8 @@ private: deselectItems(); } - void onBrushChange(const BrushRef& brush) { - if (brush->type() == kImageBrushType) - m_owner->setActiveBrush(brush); - else { - Tool* tool = App::instance()->activeTool(); - ToolPreferences::Brush& brushPref = Preferences::instance().tool(tool).brush; - - brushPref.type(static_cast<app::gen::BrushType>(brush->type())); - - m_owner->setActiveBrush( - ContextBar::createBrushFromPreferences(&brushPref)); - } - } - ContextBar* m_owner; + AppBrushes& m_brushes; BrushPopup m_popupWindow; }; @@ -1633,85 +1656,18 @@ void ContextBar::updateAutoSelectLayer(bool state) m_autoSelectLayer->setSelected(state); } -int ContextBar::addBrush(const doc::BrushRef& brush) -{ - // Use an empty slot - for (size_t i=0; i<m_brushes.size(); ++i) { - if (!m_brushes[i].locked || - !m_brushes[i].brush) { - m_brushes[i].brush = brush; - return i+1; - } - } - - m_brushes.push_back(BrushSlot(brush)); - return (int)m_brushes.size(); // Returns the slot -} - -void ContextBar::removeBrush(int slot) -{ - --slot; - if (slot >= 0 && slot < (int)m_brushes.size()) { - m_brushes[slot].brush.reset(); - - // Erase empty trailing slots - while (!m_brushes.empty() && - !m_brushes[m_brushes.size()-1].brush) - m_brushes.erase(--m_brushes.end()); - } -} - -void ContextBar::removeAllBrushes() -{ - while (!m_brushes.empty()) - m_brushes.erase(--m_brushes.end()); -} - void ContextBar::setActiveBrushBySlot(int slot) { - --slot; - if (slot >= 0 && slot < (int)m_brushes.size() && - m_brushes[slot].brush) { - m_brushes[slot].locked = true; - setActiveBrush(m_brushes[slot].brush); - } -} - -Brushes ContextBar::getBrushes() -{ - Brushes brushes; - for (const auto& slot : m_brushes) - brushes.push_back(slot.brush); - return brushes; -} - -void ContextBar::lockBrushSlot(int slot) -{ - --slot; - if (slot >= 0 && slot < (int)m_brushes.size() && - m_brushes[slot].brush) { - m_brushes[slot].locked = true; - } -} + AppBrushes& brushes = App::instance()->brushes(); -void ContextBar::unlockBrushSlot(int slot) -{ - --slot; - if (slot >= 0 && slot < (int)m_brushes.size() && - m_brushes[slot].brush) { - m_brushes[slot].locked = false; + if (brushes.hasCustomBrush(slot)) { + brushes.lockCustomBrush(slot); + setActiveBrush(brushes.getCustomBrush(slot)); } -} - -bool ContextBar::isBrushSlotLocked(int slot) const -{ - --slot; - if (slot >= 0 && slot < (int)m_brushes.size() && - m_brushes[slot].brush) { - return m_brushes[slot].locked; + else { + updateForTool(App::instance()->activeTool()); + m_brushType->showPopupAndHighlightSlot(slot); } - else - return false; } void ContextBar::setActiveBrush(const doc::BrushRef& brush) diff --git a/src/app/ui/context_bar.h b/src/app/ui/context_bar.h index 097cb16..0d30e45 100644 --- a/src/app/ui/context_bar.h +++ b/src/app/ui/context_bar.h @@ -16,7 +16,6 @@ #include "base/connection.h" #include "base/observable.h" #include "doc/brush.h" -#include "doc/brushes.h" #include "ui/box.h" #include <vector> @@ -53,21 +52,10 @@ namespace app { void updateAutoSelectLayer(bool state); void setActiveBrush(const doc::BrushRef& brush); + void setActiveBrushBySlot(int slot); doc::BrushRef activeBrush(tools::Tool* tool = nullptr) const; void discardActiveBrush(); - // Adds a new brush and returns the slot number where the brush - // is now available. - int addBrush(const doc::BrushRef& brush); - void removeBrush(int slot); - void removeAllBrushes(); - void setActiveBrushBySlot(int slot); - doc::Brushes getBrushes(); - - void lockBrushSlot(int slot); - void unlockBrushSlot(int slot); - bool isBrushSlotLocked(int slot) const; - static doc::BrushRef createBrushFromPreferences( ToolPreferences::Brush* brushPref = nullptr); @@ -91,21 +79,6 @@ namespace app { void onSymmetryModeChange(); void onDropPixels(ContextBarObserver::DropAction action); - struct BrushSlot { - // True if the user locked the brush using the shortcut key to - // access it. - bool locked; - - // Can be null if the user deletes the brush. - doc::BrushRef brush; - - BrushSlot(const doc::BrushRef& brush) - : locked(false), brush(brush) { - } - }; - - typedef std::vector<BrushSlot> BrushSlots; - class BrushTypeField; class BrushAngleField; class BrushSizeField; @@ -155,7 +128,6 @@ namespace app { RotAlgorithmField* m_rotAlgo; DropPixelsField* m_dropPixels; doc::BrushRef m_activeBrush; - BrushSlots m_brushes; ui::Label* m_selectBoxHelp; SymmetryField* m_symmetry; base::ScopedConnection m_sizeConn; -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

