We can delete brushes right-clicking them and selecting "Delete"

This commit is contained in:
David Capello 2015-04-29 15:00:05 -03:00
parent 1b25c4e9e9
commit edbff42dc8
4 changed files with 122 additions and 41 deletions

View File

@ -13,6 +13,7 @@
#include "app/commands/commands.h"
#include "app/modules/palettes.h"
#include "app/ui/app_menuitem.h"
#include "app/ui/button_set.h"
#include "app/ui/keyboard_shortcuts.h"
#include "app/ui/skin/skin_theme.h"
@ -23,8 +24,11 @@
#include "doc/palette.h"
#include "gfx/border.h"
#include "gfx/region.h"
#include "she/scoped_surface_lock.h"
#include "she/surface.h"
#include "she/system.h"
#include "ui/menu.h"
#include "ui/message.h"
#include "ui/tooltips.h"
namespace app {
@ -35,8 +39,11 @@ using namespace ui;
class Item : public ButtonSet::Item {
public:
Item(const BrushRef& brush)
: m_brush(brush) {
Item(BrushPopup* popup, BrushPopupDelegate* delegate, const BrushRef& brush, int slot = -1)
: m_popup(popup)
, m_delegate(delegate)
, m_brush(brush)
, m_slot(slot) {
setIcon(BrushPopup::createSurfaceForBrush(brush));
}
@ -44,16 +51,47 @@ public:
icon()->dispose();
}
const BrushRef& brush() const { return m_brush; }
const BrushRef& brush() const {
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 deleteItem("Delete");
deleteItem.Click.connect(&Item::onDeleteBrush, this);
menu.addChild(&deleteItem);
// 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);
}
}
return ButtonSet::Item::onProcessMessage(msg);
}
private:
void onDeleteBrush() {
m_delegate->onDeleteBrushSlot(m_slot);
}
BrushPopup* m_popup;
BrushPopupDelegate* m_delegate;
BrushRef m_brush;
int m_slot;
};
static BrushRef defBrushes[3];
BrushPopup::BrushPopup()
BrushPopup::BrushPopup(BrushPopupDelegate* delegate)
: PopupWindow("", kCloseOnClickInOtherWindow)
, m_delegate(delegate)
{
setAutoRemap(false);
setBorder(gfx::Border(0));
@ -66,7 +104,8 @@ void BrushPopup::setBrush(Brush* brush)
Item* item = static_cast<Item*>(child);
// Same type and same image
if (item->brush()->type() == brush->type() &&
if (item->brush() &&
item->brush()->type() == brush->type() &&
(brush->type() != kImageBrushType ||
item->brush()->image() == brush->image())) {
m_buttons->setSelectedItem(item);
@ -93,13 +132,13 @@ void BrushPopup::regenerate(const gfx::Rect& box, const Brushes& brushes)
}
m_buttons.reset(new ButtonSet(3 + brushes.size()));
m_buttons->addItem(new Item(defBrushes[0]));
m_buttons->addItem(new Item(defBrushes[1]));
m_buttons->addItem(new Item(defBrushes[2]));
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]));
int slot = 1;
for (const auto& brush : brushes) {
Item* item = new Item(brush);
Item* item = new Item(this, m_delegate, brush, slot);
m_buttons->addItem(item);
Params params;
@ -129,38 +168,46 @@ void BrushPopup::regenerate(const gfx::Rect& box, const Brushes& brushes)
void BrushPopup::onButtonChange()
{
Item* item = static_cast<Item*>(m_buttons->getItem(m_buttons->selectedItem()));
BrushChange(item->brush());
if (item->brush())
BrushChange(item->brush());
}
// static
she::Surface* BrushPopup::createSurfaceForBrush(const BrushRef& origBrush)
{
Image* image = nullptr;
BrushRef brush = origBrush;
if (brush->type() != kImageBrushType && brush->size() > 10) {
brush.reset(new Brush(*brush));
brush->setSize(10);
if (brush) {
if (brush->type() != kImageBrushType && brush->size() > 10) {
brush.reset(new Brush(*brush));
brush->setSize(10);
}
image = brush->image();
}
Image* image = brush->image();
she::Surface* surface = she::instance()->createRgbaSurface(
std::min(10, image->width()),
std::min(10, image->height()));
std::min(10, image ? image->width(): 4),
std::min(10, image ? image->height(): 4));
Palette* palette = get_current_palette();
if (image->pixelFormat() == IMAGE_BITMAP) {
palette = new Palette(frame_t(0), 2);
palette->setEntry(0, rgba(0, 0, 0, 0));
palette->setEntry(1, rgba(0, 0, 0, 255));
if (image) {
Palette* palette = get_current_palette();
if (image->pixelFormat() == IMAGE_BITMAP) {
palette = new Palette(frame_t(0), 2);
palette->setEntry(0, rgba(0, 0, 0, 0));
palette->setEntry(1, rgba(0, 0, 0, 255));
}
convert_image_to_surface(
image, palette, surface,
0, 0, 0, 0, image->width(), image->height());
if (image->pixelFormat() == IMAGE_BITMAP)
delete palette;
}
else {
she::ScopedSurfaceLock lock(surface);
lock->clear();
}
convert_image_to_surface(
image, palette, surface,
0, 0, 0, 0, image->width(), image->height());
if (image->pixelFormat() == IMAGE_BITMAP)
delete palette;
return surface;
}

View File

@ -19,15 +19,22 @@ namespace doc {
}
namespace ui {
class Menu;
class TooltipManager;
}
namespace app {
class ButtonSet;
class BrushPopupDelegate {
public:
virtual ~BrushPopupDelegate() { }
virtual void onDeleteBrushSlot(int slot) = 0;
};
class BrushPopup : public ui::PopupWindow {
public:
BrushPopup();
BrushPopup(BrushPopupDelegate* delegate);
void setBrush(doc::Brush* brush);
void regenerate(const gfx::Rect& box, const doc::Brushes& brushes);
@ -45,6 +52,7 @@ namespace app {
base::SharedPtr<ButtonSet> m_buttons;
ui::TooltipManager* m_tooltipManager;
BrushPopupDelegate* m_delegate;
};
} // namespace app

View File

@ -37,7 +37,6 @@
#include "doc/conversion_she.h"
#include "doc/image.h"
#include "doc/palette.h"
#include "she/scoped_surface_lock.h"
#include "she/surface.h"
#include "she/system.h"
#include "ui/button.h"
@ -59,15 +58,14 @@ using namespace tools;
static bool g_updatingFromTool = false;
class ContextBar::BrushTypeField : public ButtonSet {
class ContextBar::BrushTypeField : public ButtonSet
, public BrushPopupDelegate {
public:
BrushTypeField(ContextBar* owner)
: ButtonSet(1)
, m_owner(owner) {
m_bitmap = she::instance()->createRgbaSurface(8, 8);
she::ScopedSurfaceLock lock(m_bitmap);
lock->clear();
, m_owner(owner)
, m_bitmap(BrushPopup::createSurfaceForBrush(BrushRef(nullptr)))
, m_popupWindow(this) {
addItem(m_bitmap);
}
@ -105,18 +103,28 @@ protected:
ev.setPreferredSize(Size(16, 18)*guiscale());
}
// BrushPopupDelegate impl
void onDeleteBrushSlot(int slot) override {
m_owner->removeBrush(slot);
}
private:
void openPopup() {
// Returns a little rectangle that can be used by the popup as the
// first brush position.
gfx::Rect getPopupBox() {
Rect rc = getBounds();
rc.y += rc.h - 2*guiscale();
rc.setSize(getPreferredSize());
return rc;
}
void openPopup() {
ISettings* settings = UIContext::instance()->settings();
Tool* currentTool = settings->getCurrentTool();
IBrushSettings* brushSettings = settings->getToolSettings(currentTool)->getBrush();
doc::BrushRef brush = m_owner->activeBrush();
m_popupWindow.regenerate(rc, m_owner->brushes());
m_popupWindow.regenerate(getPopupBox(), m_owner->brushes());
m_popupWindow.setBrush(brush.get());
Region rgn(m_popupWindow.getBounds().createUnion(getBounds()));
@ -1009,15 +1017,32 @@ void ContextBar::updateAutoSelectLayer(bool 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]) {
m_brushes[i] = brush;
return i+1;
}
}
m_brushes.push_back(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].reset();
}
void ContextBar::setActiveBrushBySlot(int slot)
{
--slot;
if (slot >= 0 && slot < (int)m_brushes.size())
if (slot >= 0 && slot < (int)m_brushes.size() &&
m_brushes[slot]) {
setActiveBrush(m_brushes[slot]);
}
}
void ContextBar::setActiveBrush(const doc::BrushRef& brush)

View File

@ -52,6 +52,7 @@ namespace app {
// 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);
const doc::Brushes& brushes() const { return m_brushes; }
void setActiveBrushBySlot(int slot);