diff --git a/data/gui.xml b/data/gui.xml
index 2bd923aa4..2b2fadd3f 100644
--- a/data/gui.xml
+++ b/data/gui.xml
@@ -18,7 +18,7 @@
-
+
@@ -777,7 +777,8 @@
-
+
+
diff --git a/data/palettes/edg16.gpl b/data/palettes/edg16.gpl
new file mode 100644
index 000000000..5b8d7c991
--- /dev/null
+++ b/data/palettes/edg16.gpl
@@ -0,0 +1,21 @@
+GIMP Palette
+#
+# By ENDESGA Studios
+# https://twitter.com/ENDESGA
+#
+228 166 114 Birch
+184 111 80 Oak
+116 63 57 Pine
+ 63 40 50 Darkbark
+158 40 53 Blood
+229 59 68 Fabric
+251 146 43 Candle
+255 231 98 Glow
+ 99 198 77 Flora
+ 50 115 69 Moss
+ 25 61 63 Mold
+ 79 103 129 Iron
+175 191 210 Aluminium
+255 255 255 White
+ 44 232 244 Ion
+ 4 132 209 Archaeon
diff --git a/data/palettes/edg32.gpl b/data/palettes/edg32.gpl
new file mode 100644
index 000000000..d30fbb9c2
--- /dev/null
+++ b/data/palettes/edg32.gpl
@@ -0,0 +1,37 @@
+GIMP Palette
+#
+# By ENDESGA Studios
+# https://twitter.com/ENDESGA
+#
+190 74 47 Tetanus
+216 118 68 Rust
+234 212 170 Birch
+228 166 114 Sap
+184 111 80 Oak
+116 63 57 Pine
+ 63 40 50 Darkbark
+158 40 53 Blood
+228 59 68 Fabric
+247 118 34 Amber
+254 174 52 Glow
+254 231 97 Light
+ 99 199 77 Glade
+ 62 137 72 Flora
+ 38 92 66 Moss
+ 25 60 62 Mold
+ 18 78 137 Deep
+ 0 149 233 Archaeon
+ 44 232 245 Ion
+255 255 255 White
+192 203 220 Aluminium
+139 155 180 Zinc
+ 90 105 136 Iron
+ 58 68 102 Steel
+ 38 43 68 Shade
+255 0 68 Iiem
+ 24 20 37 Ink
+104 56 108 Lilac
+181 80 136 Petal
+246 117 122 Peach
+232 183 150 Skin
+194 133 105 Shadeskin
diff --git a/data/pref.xml b/data/pref.xml
index 28a6db333..5b91813b2 100644
--- a/data/pref.xml
+++ b/data/pref.xml
@@ -86,6 +86,7 @@
@@ -280,6 +280,7 @@
+
diff --git a/data/skins/default/skin.xml b/data/skins/default/skin.xml
index 1da076712..290f0cb40 100644
--- a/data/skins/default/skin.xml
+++ b/data/skins/default/skin.xml
@@ -192,8 +192,8 @@
-
-
+
+
@@ -212,10 +212,10 @@
-
-
-
-
+
+
+
+
diff --git a/src/app/commands/cmd_change_brush.cpp b/src/app/commands/cmd_change_brush.cpp
index fc52888d9..77fb64cf2 100644
--- a/src/app/commands/cmd_change_brush.cpp
+++ b/src/app/commands/cmd_change_brush.cpp
@@ -15,6 +15,7 @@
#include "app/commands/params.h"
#include "app/context.h"
#include "app/pref/preferences.h"
+#include "app/tools/active_tool.h"
#include "app/tools/tool.h"
#include "app/ui/context_bar.h"
#include "base/convert_to.h"
@@ -71,7 +72,9 @@ void ChangeBrushCommand::onLoadParams(const Params& params)
void ChangeBrushCommand::onExecute(Context* context)
{
- tools::Tool* tool = App::instance()->activeTool();
+ // Change the brush of the selected tool in the toolbar (not the
+ // active tool which might be different, e.g. the quick tool)
+ tools::Tool* tool = App::instance()->activeToolManager()->selectedTool();
ToolPreferences::Brush& brush =
Preferences::instance().tool(tool).brush;
@@ -97,7 +100,7 @@ void ChangeBrushCommand::onExecute(Context* context)
break;
case CustomBrush:
App::instance()->contextBar()
- ->setActiveBrushBySlot(m_slot);
+ ->setActiveBrushBySlot(tool, m_slot);
break;
}
}
diff --git a/src/app/commands/cmd_export_sprite_sheet.cpp b/src/app/commands/cmd_export_sprite_sheet.cpp
index b509703cc..4b974aa07 100644
--- a/src/app/commands/cmd_export_sprite_sheet.cpp
+++ b/src/app/commands/cmd_export_sprite_sheet.cpp
@@ -769,6 +769,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
if (!window.ok())
return;
+ docPref.spriteSheet.defined(true);
docPref.spriteSheet.type(window.spriteSheetTypeValue());
docPref.spriteSheet.columns(window.columnsValue());
docPref.spriteSheet.rows(window.rowsValue());
@@ -790,6 +791,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
// Default preferences for future sprites
DocumentPreferences& defPref(Preferences::instance().document(nullptr));
defPref.spriteSheet = docPref.spriteSheet;
+ defPref.spriteSheet.defined(false);
if (!defPref.spriteSheet.textureFilename().empty())
defPref.spriteSheet.textureFilename.setValueAndDefault(kSpecifiedFilename);
if (!defPref.spriteSheet.dataFilename().empty())
diff --git a/src/app/commands/cmd_layer_properties.cpp b/src/app/commands/cmd_layer_properties.cpp
index 5bb90d961..72c7b7be1 100644
--- a/src/app/commands/cmd_layer_properties.cpp
+++ b/src/app/commands/cmd_layer_properties.cpp
@@ -168,6 +168,10 @@ private:
}
void onCommitChange() {
+ // Nothing to do here, as there is no layer selected.
+ if (!m_layer)
+ return;
+
base::ScopedValue switchSelf(m_selfUpdate, true, false);
m_timer.stop();
diff --git a/src/app/commands/cmd_mask_by_color.cpp b/src/app/commands/cmd_mask_by_color.cpp
index 7a5fb3f31..b30b7adaf 100644
--- a/src/app/commands/cmd_mask_by_color.cpp
+++ b/src/app/commands/cmd_mask_by_color.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -103,7 +103,8 @@ void MaskByColorCommand::onExecute(Context* context)
m_buttonColor = new ColorButton
(get_config_color("MaskColor", "Color",
ColorBar::instance()->getFgColor()),
- sprite->pixelFormat());
+ sprite->pixelFormat(),
+ false);
label_tolerance = new Label("Tolerance:");
m_sliderTolerance = new Slider(0, 255, get_config_int("MaskColor", "Tolerance", 0));
m_checkPreview = new CheckBox("&Preview");
diff --git a/src/app/commands/cmd_options.cpp b/src/app/commands/cmd_options.cpp
index b2638dd4c..7a800d950 100644
--- a/src/app/commands/cmd_options.cpp
+++ b/src/app/commands/cmd_options.cpp
@@ -68,11 +68,11 @@ public:
, m_globPref(m_pref.document(nullptr))
, m_docPref(m_pref.document(context->activeDocument()))
, m_curPref(&m_docPref)
- , m_checked_bg_color1(new ColorButton(app::Color::fromMask(), IMAGE_RGB))
- , m_checked_bg_color2(new ColorButton(app::Color::fromMask(), IMAGE_RGB))
- , m_pixelGridColor(new ColorButton(app::Color::fromMask(), IMAGE_RGB))
- , m_gridColor(new ColorButton(app::Color::fromMask(), IMAGE_RGB))
- , m_cursorColor(new ColorButton(m_pref.cursor.cursorColor(), IMAGE_RGB))
+ , m_checked_bg_color1(new ColorButton(app::Color::fromMask(), IMAGE_RGB, false))
+ , m_checked_bg_color2(new ColorButton(app::Color::fromMask(), IMAGE_RGB, false))
+ , m_pixelGridColor(new ColorButton(app::Color::fromMask(), IMAGE_RGB, false))
+ , m_gridColor(new ColorButton(app::Color::fromMask(), IMAGE_RGB, false))
+ , m_cursorColor(new ColorButton(m_pref.cursor.cursorColor(), IMAGE_RGB, false))
, m_curSection(curSection)
{
sectionListbox()->Change.connect(base::Bind(&OptionsWindow::onChangeSection, this));
@@ -173,7 +173,7 @@ public:
uiScale()->setSelectedItemIndex(
uiScale()->findItemIndexByValue(
- base::convert_to(m_pref.experimental.uiScale())));
+ base::convert_to(m_pref.general.uiScale())));
if ((int(she::instance()->capabilities()) &
int(she::Capabilities::GpuAccelerationSwitch)) == int(she::Capabilities::GpuAccelerationSwitch)) {
@@ -312,8 +312,8 @@ public:
}
int newUIScale = base::convert_to(uiScale()->getValue());
- if (newUIScale != m_pref.experimental.uiScale()) {
- m_pref.experimental.uiScale(newUIScale);
+ if (newUIScale != m_pref.general.uiScale()) {
+ m_pref.general.uiScale(newUIScale);
warnings += "<<- UI Elements Scale";
}
diff --git a/src/app/commands/cmd_repeat_last_export.cpp b/src/app/commands/cmd_repeat_last_export.cpp
index ab80da20a..b59d498b9 100644
--- a/src/app/commands/cmd_repeat_last_export.cpp
+++ b/src/app/commands/cmd_repeat_last_export.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -51,8 +51,7 @@ void RepeatLastExportCommand::onExecute(Context* context)
DocumentPreferences& docPref =
Preferences::instance().document(document);
- params.set("ui",
- (docPref.spriteSheet.type() == app::SpriteSheetType::None ? "1": "0"));
+ params.set("ui", (docPref.spriteSheet.defined() ? "0": "1"));
}
context->executeCommand(cmd, params);
diff --git a/src/app/commands/cmd_sprite_properties.cpp b/src/app/commands/cmd_sprite_properties.cpp
index ff1360290..12907c58c 100644
--- a/src/app/commands/cmd_sprite_properties.cpp
+++ b/src/app/commands/cmd_sprite_properties.cpp
@@ -106,7 +106,8 @@ void SpritePropertiesCommand::onExecute(Context* context)
if (sprite->pixelFormat() == IMAGE_INDEXED) {
color_button = new ColorButton(app::Color::fromIndex(sprite->transparentColor()),
- IMAGE_INDEXED);
+ IMAGE_INDEXED,
+ false);
window.transparentColorPlaceholder()->addChild(color_button);
}
diff --git a/src/app/file/palette_file.cpp b/src/app/file/palette_file.cpp
index 3ae5ae218..2193cefd6 100644
--- a/src/app/file/palette_file.cpp
+++ b/src/app/file/palette_file.cpp
@@ -18,6 +18,7 @@
#include "doc/cel.h"
#include "doc/file/col_file.h"
#include "doc/file/gpl_file.h"
+#include "doc/file/hex_file.h"
#include "doc/file/pal_file.h"
#include "doc/image.h"
#include "doc/layer.h"
@@ -33,14 +34,14 @@ using namespace doc;
std::string get_readable_palette_extensions()
{
std::string buf = get_readable_extensions();
- buf += ",col,gpl,pal";
+ buf += ",col,gpl,hex,pal";
return buf;
}
std::string get_writable_palette_extensions()
{
std::string buf = get_writable_extensions();
- buf += ",col,gpl,pal";
+ buf += ",col,gpl,hex,pal";
return buf;
}
@@ -55,6 +56,9 @@ Palette* load_palette(const char *filename)
else if (ext == "gpl") {
pal = doc::file::load_gpl_file(filename);
}
+ else if (ext == "hex") {
+ pal = doc::file::load_hex_file(filename);
+ }
else if (ext == "pal") {
pal = doc::file::load_pal_file(filename);
}
@@ -101,13 +105,16 @@ bool save_palette(const char *filename, const Palette* pal, int columns)
else if (ext == "gpl") {
success = doc::file::save_gpl_file(pal, filename);
}
+ else if (ext == "hex") {
+ success = doc::file::save_hex_file(pal, filename);
+ }
else if (ext == "pal") {
success = doc::file::save_pal_file(pal, filename);
}
else {
FileFormat* ff = FileFormatsManager::instance()->getFileFormatByExtension(ext.c_str());
if (ff && ff->support(FILE_SUPPORT_SAVE)) {
- int w = (columns > 0 ? columns: pal->size());
+ int w = (columns > 0 ? MID(0, columns, pal->size()): pal->size());
int h = (pal->size() / w) + (pal->size() % w > 0 ? 1: 0);
app::Context tmpContext;
@@ -118,18 +125,25 @@ bool save_palette(const char *filename, const Palette* pal, int columns)
Sprite* sprite = doc->sprite();
doc->sprite()->setPalette(pal, false);
- Layer* layer = sprite->root()->firstLayer();
+ LayerImage* layer = static_cast(sprite->root()->firstLayer());
+ layer->configureAsBackground();
+
Image* image = layer->cel(frame_t(0))->image();
+ image->clear(0);
int x, y, c;
for (y=c=0; ycolorMode() == doc::ColorMode::INDEXED)
image->putPixel(x, y, c);
else
image->putPixel(x, y, pal->entry(c));
+
+ if (++c == pal->size())
+ goto done;
}
}
+ done:;
doc->setFilename(filename);
success = (save_document(&tmpContext, doc) == 0);
diff --git a/src/app/modules/gui.cpp b/src/app/modules/gui.cpp
index 87698e8cc..5ab764a04 100644
--- a/src/app/modules/gui.cpp
+++ b/src/app/modules/gui.cpp
@@ -179,7 +179,7 @@ int init_module_gui()
// Setup the GUI theme for all widgets
gui_theme = new SkinTheme();
- gui_theme->setScale(Preferences::instance().experimental.uiScale());
+ gui_theme->setScale(Preferences::instance().general.uiScale());
CurrentTheme::set(gui_theme);
if (maximized)
diff --git a/src/app/tools/symmetries.cpp b/src/app/tools/symmetries.cpp
index 4bcbb1f98..a2e70cca0 100644
--- a/src/app/tools/symmetries.cpp
+++ b/src/app/tools/symmetries.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2015 David Capello
+// Copyright (C) 2015-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -10,6 +10,7 @@
#include "app/tools/symmetries.h"
+#include "app/tools/point_shape.h"
#include "app/tools/stroke.h"
#include "app/tools/tool_loop.h"
#include "doc/brush.h"
@@ -20,7 +21,11 @@ namespace tools {
void HorizontalSymmetry::generateStrokes(const Stroke& mainStroke, Strokes& strokes,
ToolLoop* loop)
{
- int adjust = (loop->getBrush()->bounds().w % 2);
+ int adjust;
+ if (loop->getPointShape()->isFloodFill())
+ adjust = 1;
+ else
+ adjust = (loop->getBrush()->bounds().w % 2);
strokes.push_back(mainStroke);
@@ -33,7 +38,11 @@ void HorizontalSymmetry::generateStrokes(const Stroke& mainStroke, Strokes& stro
void VerticalSymmetry::generateStrokes(const Stroke& mainStroke, Strokes& strokes,
ToolLoop* loop)
{
- int adjust = (loop->getBrush()->bounds().h % 2);
+ int adjust;
+ if (loop->getPointShape()->isFloodFill())
+ adjust = 1;
+ else
+ adjust = (loop->getBrush()->bounds().h % 2);
strokes.push_back(mainStroke);
diff --git a/src/app/ui/brush_popup.cpp b/src/app/ui/brush_popup.cpp
index eb63a4215..f6da99288 100644
--- a/src/app/ui/brush_popup.cpp
+++ b/src/app/ui/brush_popup.cpp
@@ -91,11 +91,11 @@ public:
private:
void onClick() override {
ContextBar* contextBar = App::instance()->contextBar();
+ tools::Tool* tool = App::instance()->activeTool();
if (m_slot >= 0)
- contextBar->setActiveBrushBySlot(m_slot);
+ contextBar->setActiveBrushBySlot(tool, m_slot);
else if (m_brush.hasBrush()) {
- tools::Tool* tool = App::instance()->activeTool();
auto& brushPref = Preferences::instance().tool(tool).brush;
BrushRef brush;
diff --git a/src/app/ui/color_bar.cpp b/src/app/ui/color_bar.cpp
index 21738c1bb..23e847ba0 100644
--- a/src/app/ui/color_bar.cpp
+++ b/src/app/ui/color_bar.cpp
@@ -139,8 +139,8 @@ ColorBar::ColorBar(int align)
, m_tintShadeTone(nullptr)
, m_spectrum(nullptr)
, m_wheel(nullptr)
- , m_fgColor(app::Color::fromRgb(255, 255, 255), IMAGE_RGB)
- , m_bgColor(app::Color::fromRgb(0, 0, 0), IMAGE_RGB)
+ , m_fgColor(app::Color::fromRgb(255, 255, 255), IMAGE_RGB, true)
+ , m_bgColor(app::Color::fromRgb(0, 0, 0), IMAGE_RGB, true)
, m_fgWarningIcon(new WarningIcon)
, m_bgWarningIcon(new WarningIcon)
, m_lock(false)
@@ -183,12 +183,7 @@ ColorBar::ColorBar(int align)
setColorSelector(
Preferences::instance().colorBar.selector());
- Box* buttonsBox = new HBox();
- buttonsBox->addChild(&m_buttons);
- m_buttons.setMaxSize(gfx::Size(m_buttons.maxSize().w,
- 16*ui::guiscale()));
-
- addChild(buttonsBox);
+ addChild(&m_buttons);
addChild(&m_splitter);
HBox* fgBox = new HBox;
@@ -202,6 +197,8 @@ ColorBar::ColorBar(int align)
addChild(fgBox);
addChild(bgBox);
+ m_fgColor.setId("fg_color");
+ m_bgColor.setId("bg_color");
m_fgColor.setExpansive(true);
m_bgColor.setExpansive(true);
@@ -236,6 +233,8 @@ ColorBar::ColorBar(int align)
m_buttons.addItem(theme->parts.palSort());
m_buttons.addItem(theme->parts.palPresets());
m_buttons.addItem(theme->parts.palOptions());
+ m_buttons.setMaxSize(gfx::Size(m_buttons.sizeHint().w,
+ 16*ui::guiscale()));
// Tooltips
TooltipManager* tooltipManager = new TooltipManager();
diff --git a/src/app/ui/color_button.cpp b/src/app/ui/color_button.cpp
index 2172f48dd..bd99d41bc 100644
--- a/src/app/ui/color_button.cpp
+++ b/src/app/ui/color_button.cpp
@@ -25,6 +25,7 @@
#include "doc/layer.h"
#include "doc/site.h"
#include "doc/sprite.h"
+#include "gfx/rect_io.h"
#include "ui/size_hint_event.h"
#include "ui/ui.h"
@@ -41,12 +42,15 @@ static WidgetType colorbutton_type()
return type;
}
-ColorButton::ColorButton(const app::Color& color, PixelFormat pixelFormat)
+ColorButton::ColorButton(const app::Color& color,
+ PixelFormat pixelFormat,
+ bool canPinSelector)
: ButtonBase("", colorbutton_type(), kButtonWidget, kButtonWidget)
, m_color(color)
, m_pixelFormat(pixelFormat)
, m_window(NULL)
, m_dependOnLayer(false)
+ , m_canPinSelector(canPinSelector)
{
this->setFocusStop(true);
@@ -102,6 +106,13 @@ bool ColorButton::onProcessMessage(Message* msg)
{
switch (msg->type()) {
+ case kOpenMessage:
+ if (!m_windowDefaultBounds.isEmpty() &&
+ this->isVisible()) {
+ openSelectorDialog();
+ }
+ break;
+
case kCloseMessage:
if (m_window && m_window->isVisible())
m_window->closeWindow(NULL);
@@ -233,34 +244,65 @@ void ColorButton::onClick(Event& ev)
}
}
+void ColorButton::onLoadLayout(ui::LoadLayoutEvent& ev)
+{
+ if (m_canPinSelector) {
+ bool pinned = false;
+ ev.stream() >> pinned;
+ if (ev.stream() && pinned)
+ ev.stream() >> m_windowDefaultBounds;
+ }
+}
+
+void ColorButton::onSaveLayout(ui::SaveLayoutEvent& ev)
+{
+ if (m_canPinSelector && m_window && m_window->isPinned())
+ ev.stream() << 1 << ' ' << m_window->bounds();
+ else
+ ev.stream() << 0;
+}
+
void ColorButton::openSelectorDialog()
{
- int x, y;
+ bool pinned = (!m_windowDefaultBounds.isEmpty());
if (m_window == NULL) {
- m_window = new ColorPopup();
+ m_window = new ColorPopup(m_canPinSelector);
m_window->ColorChange.connect(&ColorButton::onWindowColorChange, this);
}
+ if (pinned)
+ m_window->setPinned(true);
+
m_window->setColor(m_color, ColorPopup::ChangeType);
m_window->openWindow();
- x = MID(0, bounds().x, ui::display_w()-m_window->bounds().w);
- if (bounds().y2() <= ui::display_h()-m_window->bounds().h)
- y = MAX(0, bounds().y2());
- else
- y = MAX(0, bounds().y-m_window->bounds().h);
-
- m_window->positionWindow(x, y);
+ gfx::Rect winBounds = m_windowDefaultBounds;
+ if (!pinned) {
+ winBounds = gfx::Rect(m_window->bounds().origin(),
+ m_window->sizeHint());
+ winBounds.x = MID(0, bounds().x, ui::display_w()-winBounds.w);
+ if (bounds().y2() <= ui::display_h()-winBounds.h)
+ winBounds.y = MAX(0, bounds().y2());
+ else
+ winBounds.y = MAX(0, bounds().y-winBounds.h);
+ }
+ winBounds.x = MID(0, winBounds.x, ui::display_w()-winBounds.w);
+ winBounds.y = MID(0, winBounds.y, ui::display_h()-winBounds.h);
+ m_window->setBounds(winBounds);
m_window->manager()->dispatchMessages();
m_window->layout();
// Setup the hot-region
- gfx::Rect rc = bounds().createUnion(m_window->bounds());
- rc.enlarge(8);
- gfx::Region rgn(rc);
- static_cast(m_window)->setHotRegion(rgn);
+ if (!pinned) {
+ gfx::Rect rc = bounds().createUnion(m_window->bounds());
+ rc.enlarge(8);
+ gfx::Region rgn(rc);
+ static_cast(m_window)->setHotRegion(rgn);
+ }
+
+ m_windowDefaultBounds = gfx::Rect();
}
void ColorButton::closeSelectorDialog()
@@ -278,6 +320,24 @@ void ColorButton::onActiveSiteChange(const Site& site)
{
if (m_dependOnLayer)
invalidate();
+
+ if (m_canPinSelector) {
+ // Hide window
+ if (!site.document()) {
+ if (m_window)
+ m_window->setVisible(false);
+ }
+ // Show window if it's pinned
+ else {
+ // Check if it's pinned from the preferences (m_windowDefaultBounds)
+ if (!m_window && !m_windowDefaultBounds.isEmpty())
+ openSelectorDialog();
+ // Or check if the window was hidden but it's pinned, so we've
+ // to show it again.
+ else if (m_window && m_window->isPinned())
+ m_window->setVisible(true);
+ }
+ }
}
} // namespace app
diff --git a/src/app/ui/color_button.h b/src/app/ui/color_button.h
index ec223d000..46c990d5f 100644
--- a/src/app/ui/color_button.h
+++ b/src/app/ui/color_button.h
@@ -22,7 +22,9 @@ namespace app {
, public doc::ContextObserver
, public IColorSource {
public:
- ColorButton(const app::Color& color, PixelFormat pixelFormat);
+ ColorButton(const app::Color& color,
+ PixelFormat pixelFormat,
+ bool canPinSelector);
~ColorButton();
PixelFormat pixelFormat() const;
@@ -43,6 +45,8 @@ namespace app {
void onSizeHint(ui::SizeHintEvent& ev) override;
void onPaint(ui::PaintEvent& ev) override;
void onClick(ui::Event& ev) override;
+ void onLoadLayout(ui::LoadLayoutEvent& ev) override;
+ void onSaveLayout(ui::SaveLayoutEvent& ev) override;
private:
void openSelectorDialog();
@@ -53,7 +57,9 @@ namespace app {
app::Color m_color;
PixelFormat m_pixelFormat;
ColorPopup* m_window;
+ gfx::Rect m_windowDefaultBounds;
bool m_dependOnLayer;
+ bool m_canPinSelector;
};
} // namespace app
diff --git a/src/app/ui/color_popup.cpp b/src/app/ui/color_popup.cpp
index 357053037..979f2e108 100644
--- a/src/app/ui/color_popup.cpp
+++ b/src/app/ui/color_popup.cpp
@@ -47,7 +47,7 @@ enum {
MASK_MODE
};
-ColorPopup::ColorPopup()
+ColorPopup::ColorPopup(bool canPin)
: PopupWindowPin("Color Selector", ClickBehavior::CloseOnClickInOtherWindow)
, m_vbox(VERTICAL)
, m_topBox(HORIZONTAL)
@@ -55,6 +55,7 @@ ColorPopup::ColorPopup()
, m_colorPalette(false, PaletteView::SelectOneColor, this, 7*guiscale())
, m_colorType(5)
, m_maskLabel("Transparent Color Selected")
+ , m_canPin(canPin)
, m_disableHexUpdate(false)
{
m_colorType.addItem("Index");
@@ -69,6 +70,9 @@ ColorPopup::ColorPopup()
m_colorPaletteContainer.attachToView(&m_colorPalette);
m_colorPaletteContainer.setExpansive(true);
+ m_rgbSliders.setExpansive(true);
+ m_hsvSliders.setExpansive(true);
+ m_graySlider.setExpansive(true);
m_topBox.addChild(&m_colorType);
m_topBox.addChild(new Separator("", VERTICAL));
@@ -94,6 +98,9 @@ ColorPopup::ColorPopup()
m_graySlider.ColorChange.connect(&ColorPopup::onColorSlidersChange, this);
m_hexColorEntry.ColorChange.connect(&ColorPopup::onColorHexEntryChange, this);
+ if (!m_canPin)
+ showPin(false);
+
selectColorType(app::Color::RgbType);
setSizeHint(gfx::Size(300*guiscale(), sizeHint().h));
@@ -132,6 +139,26 @@ app::Color ColorPopup::getColor() const
return m_color;
}
+void ColorPopup::onMakeFloating()
+{
+ PopupWindowPin::onMakeFloating();
+
+ if (m_canPin) {
+ setSizeable(true);
+ setMoveable(true);
+ }
+}
+
+void ColorPopup::onMakeFixed()
+{
+ PopupWindowPin::onMakeFixed();
+
+ if (m_canPin) {
+ setSizeable(false);
+ setMoveable(true);
+ }
+}
+
void ColorPopup::onPaletteViewIndexChange(int index, ui::MouseButtons buttons)
{
setColorWithSignal(app::Color::fromIndex(index));
diff --git a/src/app/ui/color_popup.h b/src/app/ui/color_popup.h
index c6967ddf7..fc9899d45 100644
--- a/src/app/ui/color_popup.h
+++ b/src/app/ui/color_popup.h
@@ -31,7 +31,7 @@ namespace app {
DoNotChangeType
};
- ColorPopup();
+ ColorPopup(bool canPin);
~ColorPopup();
void setColor(const app::Color& color, SetColorOptions options);
@@ -41,6 +41,8 @@ namespace app {
base::Signal1 ColorChange;
protected:
+ void onMakeFloating() override;
+ void onMakeFixed() override;
void onColorSlidersChange(ColorSlidersChangeEvent& ev);
void onColorHexEntryChange(const app::Color& color);
void onColorTypeClick();
@@ -66,6 +68,7 @@ namespace app {
GraySlider m_graySlider;
ui::Label m_maskLabel;
base::ScopedConnection m_onPaletteChangeConn;
+ bool m_canPin;
// This variable is used to avoid updating the m_hexColorEntry text
// when the color change is generated from a
diff --git a/src/app/ui/color_sliders.cpp b/src/app/ui/color_sliders.cpp
index edd58695e..08adfaf44 100644
--- a/src/app/ui/color_sliders.cpp
+++ b/src/app/ui/color_sliders.cpp
@@ -68,6 +68,7 @@ namespace {
color = color_utils::color_for_ui(app::Color::fromHsv(m_color.getHue(), m_color.getSaturation(), 100 * x / w));
break;
case ColorSliders::Gray:
+ case ColorSliders::Alpha:
color = color_utils::color_for_ui(app::Color::fromGray(255 * x / w));
break;
}
@@ -163,9 +164,9 @@ void ColorSliders::addSlider(Channel channel, const char* labelText, int min, in
box->setMaxSize(sz);
entry->setMaxSize(sz);
- m_grid.addChildInCell(label, 1, 1, LEFT | MIDDLE);
- m_grid.addChildInCell(box, 1, 1, HORIZONTAL | VERTICAL | EXPANSIVE);
- m_grid.addChildInCell(entry, 1, 1, LEFT | MIDDLE);
+ m_grid.addChildInCell(label, 1, 1, LEFT | MIDDLE);
+ m_grid.addChildInCell(box, 1, 1, HORIZONTAL | VERTICAL);
+ m_grid.addChildInCell(entry, 1, 1, LEFT | MIDDLE);
}
void ColorSliders::setAbsSliderValue(int sliderIndex, int value)
diff --git a/src/app/ui/color_sliders.h b/src/app/ui/color_sliders.h
index 6707a4133..e3a052f01 100644
--- a/src/app/ui/color_sliders.h
+++ b/src/app/ui/color_sliders.h
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -45,7 +45,7 @@ namespace app {
base::Signal1 ColorChange;
protected:
- void onSizeHint(ui::SizeHintEvent& ev);
+ void onSizeHint(ui::SizeHintEvent& ev) override;
// For derived classes
void addSlider(Channel channel, const char* labelText, int min, int max);
diff --git a/src/app/ui/context_bar.cpp b/src/app/ui/context_bar.cpp
index 7ad3b416a..5f8a1165f 100644
--- a/src/app/ui/context_bar.cpp
+++ b/src/app/ui/context_bar.cpp
@@ -886,7 +886,7 @@ class ContextBar::TransparentColorField : public HBox {
public:
TransparentColorField(ContextBar* owner)
: m_icon(1)
- , m_maskColor(app::Color::fromMask(), IMAGE_RGB)
+ , m_maskColor(app::Color::fromMask(), IMAGE_RGB, false)
, m_owner(owner) {
SkinTheme* theme = SkinTheme::instance();
@@ -1700,14 +1700,17 @@ void ContextBar::updateAutoSelectLayer(bool state)
m_autoSelectLayer->setSelected(state);
}
-void ContextBar::setActiveBrushBySlot(int slot)
+void ContextBar::setActiveBrushBySlot(tools::Tool* tool, int slot)
{
+ ASSERT(tool);
+ if (!tool)
+ return;
+
AppBrushes& brushes = App::instance()->brushes();
BrushSlot brush = brushes.getBrushSlot(slot);
if (!brush.isEmpty()) {
brushes.lockBrushSlot(slot);
- Tool* tool = App::instance()->activeTool();
Preferences& pref = Preferences::instance();
ToolPreferences& toolPref = pref.tool(tool);
ToolPreferences::Brush& brushPref = toolPref.brush;
@@ -1752,7 +1755,7 @@ void ContextBar::setActiveBrushBySlot(int slot)
tools::FreehandAlgorithm::REGULAR));
}
else {
- updateForTool(App::instance()->activeTool());
+ updateForTool(tool);
m_brushType->showPopupAndHighlightSlot(slot);
}
}
diff --git a/src/app/ui/context_bar.h b/src/app/ui/context_bar.h
index 9e8157cd9..18f186f97 100644
--- a/src/app/ui/context_bar.h
+++ b/src/app/ui/context_bar.h
@@ -54,7 +54,7 @@ namespace app {
void updateAutoSelectLayer(bool state);
void setActiveBrush(const doc::BrushRef& brush);
- void setActiveBrushBySlot(int slot);
+ void setActiveBrushBySlot(tools::Tool* tool, int slot);
doc::BrushRef activeBrush(tools::Tool* tool = nullptr) const;
void discardActiveBrush();
diff --git a/src/app/ui/editor/moving_pixels_state.cpp b/src/app/ui/editor/moving_pixels_state.cpp
index 5ca5b5ed6..440438cfd 100644
--- a/src/app/ui/editor/moving_pixels_state.cpp
+++ b/src/app/ui/editor/moving_pixels_state.cpp
@@ -198,11 +198,28 @@ void MovingPixelsState::onActiveToolChange(Editor* editor, tools::Tool* tool)
// If the user changed the tool when he/she is moving pixels,
// we have to drop the pixels only if the new tool is not selection...
- if (m_pixelsMovement &&
- (!tool->getInk(0)->isSelection() ||
- !tool->getInk(1)->isSelection())) {
- // We have to drop pixels
- dropPixels();
+ if (m_pixelsMovement) {
+ // We don't want to drop pixels in case the user change the tool
+ // for scrolling/zooming/picking colors.
+ if ((!tool->getInk(0)->isSelection() ||
+ !tool->getInk(1)->isSelection()) &&
+ (!tool->getInk(0)->isScrollMovement() ||
+ !tool->getInk(1)->isScrollMovement()) &&
+ (!tool->getInk(0)->isZoom() ||
+ !tool->getInk(1)->isZoom()) &&
+ (!tool->getInk(0)->isEyedropper() ||
+ !tool->getInk(1)->isEyedropper())) {
+ // We have to drop pixels
+ dropPixels();
+ }
+ // If we've temporarily gone to a non-selection tool and now we're
+ // back, we've just to update the context bar to show the "moving
+ // pixels" controls (e.g. OK/Cancel movement buttons).
+ else if (tool->getInk(0)->isSelection() ||
+ tool->getInk(1)->isSelection()) {
+ ContextBar* contextBar = App::instance()->contextBar();
+ contextBar->updateForMovingPixels();
+ }
}
}
@@ -477,8 +494,13 @@ void MovingPixelsState::onBeforeCommandExecution(CommandExecutionEvent& ev)
return;
}
}
+ // Don't drop pixels if the user zooms/scrolls/picks a color
+ // using commands.
else if ((command->id() == CommandId::Zoom) ||
- (command->id() == CommandId::Scroll)) {
+ (command->id() == CommandId::Scroll) ||
+ (command->id() == CommandId::Eyedropper) ||
+ // DiscardBrush is used by Eyedropper command
+ (command->id() == CommandId::DiscardBrush)) {
// Do not drop pixels
return;
}
diff --git a/src/app/ui/font_popup.cpp b/src/app/ui/font_popup.cpp
index aa0f45dc3..8c89f9d06 100644
--- a/src/app/ui/font_popup.cpp
+++ b/src/app/ui/font_popup.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -88,8 +88,8 @@ private:
}
}
- void onSelect() override {
- if (m_image)
+ void onSelect(bool selected) override {
+ if (!selected || m_image)
return;
ListBox* listbox = static_cast(parent());
diff --git a/src/app/ui/hex_color_entry.cpp b/src/app/ui/hex_color_entry.cpp
index db2ebe7c0..66a6b6ea6 100644
--- a/src/app/ui/hex_color_entry.cpp
+++ b/src/app/ui/hex_color_entry.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -12,6 +12,7 @@
#include
#include "app/ui/hex_color_entry.h"
+#include "base/hex.h"
#include "gfx/border.h"
#include "ui/theme.h"
@@ -19,13 +20,6 @@ namespace app {
using namespace ui;
-static inline bool is_hex_digit(char digit)
-{
- return ((digit >= '0' && digit <= '9') ||
- (digit >= 'a' && digit <= 'f') ||
- (digit >= 'A' && digit <= 'F'));
-}
-
HexColorEntry::HexColorEntry()
: Box(HORIZONTAL)
, m_label("#")
@@ -56,7 +50,7 @@ void HexColorEntry::onEntryChange()
int r, g, b;
// Remove non hex digits
- while (text.size() > 0 && !is_hex_digit(text[0]))
+ while (text.size() > 0 && !base::is_hex_digit(text[0]))
text.erase(0, 1);
// Fill with zeros at the end of the text
diff --git a/src/app/ui/main_window.cpp b/src/app/ui/main_window.cpp
index 7f6b86aa6..dc97c4d01 100644
--- a/src/app/ui/main_window.cpp
+++ b/src/app/ui/main_window.cpp
@@ -15,6 +15,7 @@
#include "app/commands/commands.h"
#include "app/ini_file.h"
#include "app/modules/editors.h"
+#include "app/notification_delegate.h"
#include "app/pref/preferences.h"
#include "app/ui/color_bar.h"
#include "app/ui/context_bar.h"
@@ -35,6 +36,7 @@
#include "app/ui/workspace_tabs.h"
#include "app/ui_context.h"
#include "base/path.h"
+#include "she/display.h"
#include "ui/message.h"
#include "ui/splitter.h"
#include "ui/system.h"
@@ -44,10 +46,51 @@ namespace app {
using namespace ui;
+class ScreenScalePanic : public INotificationDelegate {
+public:
+ std::string notificationText() override {
+ return "Reset Scale!";
+ }
+
+ void notificationClick() override {
+ auto& pref = Preferences::instance();
+
+ const int newScreenScale = 2;
+ const int newUIScale = 1;
+ bool needsRestart = false;
+
+ if (pref.general.screenScale() != newScreenScale)
+ pref.general.screenScale(newScreenScale);
+
+ if (pref.general.uiScale() != newUIScale) {
+ pref.general.uiScale(newUIScale);
+ needsRestart = true;
+ }
+
+ pref.save();
+
+ // If the UI scale is greater than 100%, we would like to avoid
+ // setting the Screen Scale to 200% right now to avoid a worse
+ // effect to the user. E.g. If the UI Scale is 400% and Screen
+ // Scale is 100%, and the user choose to reset the scale, we
+ // cannot change the Screen Scale to 200% (we're going to
+ // increase the problem), so we change the Screen Scale to 100%
+ // just to show the "restart" message.
+ Manager* manager = Manager::getDefault();
+ she::Display* display = manager->getDisplay();
+ display->setScale(ui::guiscale() > newUIScale ? 1: newScreenScale);
+ manager->setDisplay(display);
+
+ if (needsRestart)
+ Alert::show("Aseprite<reload();
@@ -104,6 +147,8 @@ MainWindow::MainWindow()
MainWindow::~MainWindow()
{
+ delete m_scalePanic;
+
if (m_devConsoleView) {
if (m_devConsoleView->parent())
m_workspace->removeView(m_devConsoleView);
@@ -251,6 +296,20 @@ void MainWindow::onSaveLayout(SaveLayoutEvent& ev)
Window::onSaveLayout(ev);
}
+void MainWindow::onResize(ui::ResizeEvent& ev)
+{
+ app::gen::MainWindow::onResize(ev);
+
+ she::Display* display = manager()->getDisplay();
+ if ((display) &&
+ (display->scale()*ui::guiscale() > 2) &&
+ (!m_scalePanic) &&
+ (ui::display_w()/ui::guiscale() < 320 ||
+ ui::display_h()/ui::guiscale() < 260)) {
+ showNotification(m_scalePanic = new ScreenScalePanic);
+ }
+}
+
// When the active view is changed from methods like
// Workspace::splitView(), this function is called, and we have to
// inform to the UIContext that the current view has changed.
diff --git a/src/app/ui/main_window.h b/src/app/ui/main_window.h
index 9d5603ec6..5a7f8e51c 100644
--- a/src/app/ui/main_window.h
+++ b/src/app/ui/main_window.h
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -95,6 +95,7 @@ namespace app {
protected:
bool onProcessMessage(ui::Message* msg) override;
void onSaveLayout(ui::SaveLayoutEvent& ev) override;
+ void onResize(ui::ResizeEvent& ev) override;
void onActiveViewChange();
private:
@@ -115,6 +116,7 @@ namespace app {
HomeView* m_homeView;
DevConsoleView* m_devConsoleView;
Notifications* m_notifications;
+ INotificationDelegate* m_scalePanic;
};
}
diff --git a/src/app/ui/popup_window_pin.cpp b/src/app/ui/popup_window_pin.cpp
index d484a0d5d..2dd6192a2 100644
--- a/src/app/ui/popup_window_pin.cpp
+++ b/src/app/ui/popup_window_pin.cpp
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -40,6 +40,19 @@ PopupWindowPin::PopupWindowPin(const std::string& text, ClickBehavior clickBehav
CENTER | MIDDLE));
}
+void PopupWindowPin::showPin(bool state)
+{
+ m_pin.setVisible(state);
+}
+
+void PopupWindowPin::setPinned(bool pinned)
+{
+ m_pin.setSelected(pinned);
+
+ Event ev(this);
+ onPinClick(ev);
+}
+
void PopupWindowPin::onPinClick(Event& ev)
{
if (m_pin.isSelected()) {
@@ -57,33 +70,25 @@ bool PopupWindowPin::onProcessMessage(Message* msg)
{
switch (msg->type()) {
- case kOpenMessage:
- m_pin.setSelected(false);
- makeFixed();
- break;
-
- case kCloseMessage:
- m_pin.setSelected(false);
+ case kOpenMessage: {
+ if (!isPinned())
+ makeFixed();
break;
+ }
}
return PopupWindow::onProcessMessage(msg);
}
-void PopupWindowPin::onHitTest(HitTestEvent& ev)
+void PopupWindowPin::onWindowMovement()
{
- PopupWindow::onHitTest(ev);
+ PopupWindow::onWindowMovement();
- if ((m_pin.isSelected()) &&
- (ev.hit() == HitTestClient)) {
- if (ev.point().x <= bounds().x+2)
- ev.setHit(HitTestBorderW);
- else if (ev.point().x >= bounds().x2()-3)
- ev.setHit(HitTestBorderE);
- else
- ev.setHit(HitTestCaption);
- }
+ // If the window isn't pinned and we move it, we can automatically
+ // pin it.
+ if (!m_pin.isSelected())
+ setPinned(true);
}
} // namespace app
diff --git a/src/app/ui/popup_window_pin.h b/src/app/ui/popup_window_pin.h
index 0470ed662..5b178d720 100644
--- a/src/app/ui/popup_window_pin.h
+++ b/src/app/ui/popup_window_pin.h
@@ -1,5 +1,5 @@
// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@@ -17,9 +17,13 @@ namespace app {
public:
PopupWindowPin(const std::string& text, ClickBehavior clickBehavior);
+ void showPin(bool state);
+ bool isPinned() const { return m_pin.isSelected(); }
+ void setPinned(bool pinned);
+
protected:
virtual bool onProcessMessage(ui::Message* msg) override;
- virtual void onHitTest(ui::HitTestEvent& ev) override;
+ virtual void onWindowMovement() override;
// The pin. Your derived class must add this pin in some place of
// the frame as a children, and you must to remove the pin from the
diff --git a/src/app/ui/skin/skin_theme.cpp b/src/app/ui/skin/skin_theme.cpp
index ca541180a..c126f5ebc 100644
--- a/src/app/ui/skin/skin_theme.cpp
+++ b/src/app/ui/skin/skin_theme.cpp
@@ -1315,21 +1315,22 @@ void SkinTheme::paintSlider(PaintEvent& ev)
g->fillRect(BGCOLOR, rc);
// Draw thumb
- g->drawRgbaSurface(thumb, x-thumb->width()/2, rc.y);
+ int thumb_y = rc.y;
+ if (rc.h > thumb->height()*3)
+ rc.shrink(Border(0, thumb->height(), 0, 0));
// Draw borders
- rc.shrink(Border(
- 3 * guiscale(),
- thumb->height(),
- 3 * guiscale(),
- 1 * guiscale()));
-
- drawRect(g, rc, nw.get(), gfx::ColorNone);
+ if (rc.h > 4*guiscale()) {
+ rc.shrink(Border(3, 0, 3, 1) * guiscale());
+ drawRect(g, rc, nw.get(), gfx::ColorNone);
+ }
// Draw background (using the customized ISliderBgPainter implementation)
rc.shrink(Border(1, 1, 1, 2) * guiscale());
if (!rc.isEmpty())
bgPainter->paint(widget, g, rc);
+
+ g->drawRgbaSurface(thumb, x-thumb->width()/2, thumb_y);
}
else {
// Draw borders
diff --git a/src/app/widget_loader.cpp b/src/app/widget_loader.cpp
index 6b042081b..00ef4e1b3 100644
--- a/src/app/widget_loader.cpp
+++ b/src/app/widget_loader.cpp
@@ -420,7 +420,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
}
else if (elem_name == "colorpicker") {
if (!widget)
- widget = new ColorButton(Color::fromMask(), app_get_current_pixel_format());
+ widget = new ColorButton(Color::fromMask(), app_get_current_pixel_format(), false);
}
else if (elem_name == "dropdownbutton") {
if (!widget) {
diff --git a/src/base/hex.h b/src/base/hex.h
new file mode 100644
index 000000000..f5d743694
--- /dev/null
+++ b/src/base/hex.h
@@ -0,0 +1,21 @@
+// Aseprite Base Library
+// Copyright (c) 2016 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifndef BASE_HEX_H_INCLUDED
+#define BASE_HEX_H_INCLUDED
+#pragma once
+
+namespace base {
+
+ inline bool is_hex_digit(int digit) {
+ return ((digit >= '0' && digit <= '9') ||
+ (digit >= 'a' && digit <= 'f') ||
+ (digit >= 'A' && digit <= 'F'));
+ }
+
+} // namespace base
+
+#endif
diff --git a/src/doc/CMakeLists.txt b/src/doc/CMakeLists.txt
index 6985030a2..8d3b13b69 100644
--- a/src/doc/CMakeLists.txt
+++ b/src/doc/CMakeLists.txt
@@ -32,6 +32,7 @@ add_library(doc-lib
documents.cpp
file/col_file.cpp
file/gpl_file.cpp
+ file/hex_file.cpp
file/pal_file.cpp
frame_tag.cpp
frame_tag_io.cpp
diff --git a/src/doc/file/hex_file.cpp b/src/doc/file/hex_file.cpp
new file mode 100644
index 000000000..f202ad265
--- /dev/null
+++ b/src/doc/file/hex_file.cpp
@@ -0,0 +1,87 @@
+// Aseprite Document Library
+// Copyright (c) 2016 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "base/fstream_path.h"
+#include "base/hex.h"
+#include "base/trim_string.h"
+#include "base/unique_ptr.h"
+#include "doc/palette.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace doc {
+namespace file {
+
+Palette* load_hex_file(const char *filename)
+{
+ std::ifstream f(FSTREAM_PATH(filename));
+ if (f.bad())
+ return nullptr;
+
+ base::UniquePtr pal(new Palette(frame_t(0), 0));
+
+ // Read line by line, each line one color, ignore everything that
+ // doesn't look like a hex color.
+ std::string line;
+ while (std::getline(f, line)) {
+ // Trim line
+ base::trim_string(line, line);
+
+ // Remove comments
+ if (line.empty())
+ continue;
+
+ // Find 6 consecutive hex digits
+ for (int i=0; i> 16;
+ int g = (hex & 0xff00) >> 8;
+ int b = (hex & 0xff);
+ pal->addEntry(rgba(r, g, b, 255));
+
+ // Done, one color per line
+ break;
+ }
+ }
+
+ return pal.release();
+}
+
+bool save_hex_file(const Palette *pal, const char *filename)
+{
+ std::ofstream f(FSTREAM_PATH(filename));
+ if (f.bad()) return false;
+
+ f << std::hex << std::setfill('0');
+ for (int i=0; isize(); ++i) {
+ uint32_t col = pal->getEntry(i);
+ f << std::setw(2) << ((int)rgba_getr(col))
+ << std::setw(2) << ((int)rgba_getg(col))
+ << std::setw(2) << ((int)rgba_getb(col)) << "\n";
+ }
+
+ return true;
+}
+
+} // namespace file
+} // namespace doc
diff --git a/src/doc/file/hex_file.h b/src/doc/file/hex_file.h
new file mode 100644
index 000000000..ec0d5ca61
--- /dev/null
+++ b/src/doc/file/hex_file.h
@@ -0,0 +1,23 @@
+// Aseprite Document Library
+// Copyright (c) 2016 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifndef DOC_FILE_HEX_FILE_H_INCLUDED
+#define DOC_FILE_HEX_FILE_H_INCLUDED
+#pragma once
+
+namespace doc {
+
+ class Palette;
+
+ namespace file {
+
+ Palette* load_hex_file(const char* filename);
+ bool save_hex_file(const Palette* pal, const char* filename);
+
+ } // namespace file
+} // namespace doc
+
+#endif
diff --git a/src/gfx/LICENSE.txt b/src/gfx/LICENSE.txt
index 220ac0d42..0d2d81fd4 100644
--- a/src/gfx/LICENSE.txt
+++ b/src/gfx/LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2001-2014 David Capello
+Copyright (c) 2001-2016 David Capello
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/src/gfx/rect_io.h b/src/gfx/rect_io.h
index c455c3b2a..69be02bf7 100644
--- a/src/gfx/rect_io.h
+++ b/src/gfx/rect_io.h
@@ -1,5 +1,5 @@
// Aseprite Gfx Library
-// Copyright (C) 2001-2014 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -13,8 +13,7 @@
namespace gfx {
- inline std::ostream& operator<<(std::ostream& os, const Rect& rect)
- {
+ inline std::ostream& operator<<(std::ostream& os, const Rect& rect) {
return os << "("
<< rect.x << ", "
<< rect.y << ", "
@@ -22,6 +21,22 @@ namespace gfx {
<< rect.h << ")";
}
+ inline std::istream& operator>>(std::istream& in, Rect& rect) {
+ while (in && in.get() != '(')
+ ;
+
+ if (!in)
+ return in;
+
+ char chr;
+ in >> rect.x >> chr
+ >> rect.y >> chr
+ >> rect.w >> chr
+ >> rect.h >> chr;
+
+ return in;
+ }
+
}
#endif
diff --git a/src/gfx/region_tests.cpp b/src/gfx/region_tests.cpp
index 920b555eb..99d4ea4a4 100644
--- a/src/gfx/region_tests.cpp
+++ b/src/gfx/region_tests.cpp
@@ -1,5 +1,5 @@
// Aseprite Gfx Library
-// Copyright (C) 2001-2013 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -10,24 +10,13 @@
#include
-#include "gfx/region.h"
#include "gfx/point.h"
+#include "gfx/rect_io.h"
+#include "gfx/region.h"
using namespace std;
using namespace gfx;
-namespace gfx {
-
- ostream& operator<<(ostream& os, const Rect& rect) {
- return os << "("
- << rect.x << ", "
- << rect.y << ", "
- << rect.w << ", "
- << rect.h << ")";
- }
-
-}
-
ostream& operator<<(ostream& os, const Region& rgn)
{
os << "{";
diff --git a/src/she/osx/view.mm b/src/she/osx/view.mm
index c41110093..2c4e2b9d7 100644
--- a/src/she/osx/view.mm
+++ b/src/she/osx/view.mm
@@ -406,9 +406,19 @@ bool is_key_pressed(KeyScancode scancode)
ev.setPreciseWheel(true);
}
else {
+ // Ignore the acceleration factor, just use the wheel sign.
+ gfx::Point pt(0, 0);
+ if (event.scrollingDeltaX >= 0.1)
+ pt.x = -1;
+ else if (event.scrollingDeltaX <= -0.1)
+ pt.x = 1;
+ if (event.scrollingDeltaY >= 0.1)
+ pt.y = -1;
+ else if (event.scrollingDeltaY <= -0.1)
+ pt.y = 1;
+
ev.setPointerType(she::PointerType::Mouse);
- ev.setWheelDelta(gfx::Point(-event.scrollingDeltaX,
- -event.scrollingDeltaY));
+ ev.setWheelDelta(pt);
}
queue_event(ev);
diff --git a/src/she/skia/skia_window_osx.mm b/src/she/skia/skia_window_osx.mm
index cb299f752..d046efb6c 100644
--- a/src/she/skia/skia_window_osx.mm
+++ b/src/she/skia/skia_window_osx.mm
@@ -300,7 +300,8 @@ private:
{
NSGraphicsContext* gc = [NSGraphicsContext currentContext];
CGContextRef cg = (CGContextRef)[gc graphicsPort];
- CGImageRef img = SkCreateCGImageRef(bitmap);
+ CGColorSpaceRef colorSpace = CGDisplayCopyColorSpace(CGMainDisplayID());
+ CGImageRef img = SkCreateCGImageRefWithColorspace(bitmap, colorSpace);
if (img) {
CGRect r = CGRectMake(viewBounds.origin.x+rect.x,
viewBounds.origin.y+rect.y,
@@ -312,6 +313,7 @@ private:
CGContextRestoreGState(cg);
CGImageRelease(img);
}
+ CGColorSpaceRelease(colorSpace);
}
bitmap.unlockPixels();
}
diff --git a/src/ui/LICENSE.txt b/src/ui/LICENSE.txt
index 7ed8f201a..0d2d81fd4 100644
--- a/src/ui/LICENSE.txt
+++ b/src/ui/LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2001-2015 David Capello
+Copyright (c) 2001-2016 David Capello
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/src/ui/README.md b/src/ui/README.md
index 23ac4199f..57148f8b4 100644
--- a/src/ui/README.md
+++ b/src/ui/README.md
@@ -1,4 +1,4 @@
# Aseprite UI Library
-*Copyright (C) 2001-2014 David Capello*
+*Copyright (C) 2001-2016 David Capello*
> Distributed under [MIT license](LICENSE.txt)
diff --git a/src/ui/box.cpp b/src/ui/box.cpp
index 74bdcf83a..1f865f6b2 100644
--- a/src/ui/box.cpp
+++ b/src/ui/box.cpp
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -79,13 +79,13 @@ void Box::onSizeHint(SizeHintEvent& ev)
void Box::onResize(ResizeEvent& ev)
{
-#define LAYOUT_CHILDREN(x, w) { \
+#define LAYOUT_CHILDREN(x, y, w, h) { \
availExtraSize = availSize.w - prefSize.w; \
availSize.w -= childSpacing() * (visibleChildren-1); \
if (align() & HOMOGENEOUS) \
homogeneousSize = availSize.w / visibleChildren; \
\
- Rect childPos(childrenBounds()); \
+ Rect defChildPos(childrenBounds()); \
int i = 0, j = 0; \
for (auto child : children()) { \
if (child->hasFlags(HIDDEN)) \
@@ -111,9 +111,12 @@ void Box::onResize(ResizeEvent& ev)
} \
} \
\
- childPos.w = MAX(1, size); \
+ Rect childPos = defChildPos; \
+ childPos.w = size = MID(child->minSize().w, size, child->maxSize().w); \
+ childPos.h = MID(child->minSize().h, childPos.h, child->maxSize().h); \
child->setBounds(childPos); \
- childPos.x += size + childSpacing(); \
+ \
+ defChildPos.x += size + childSpacing(); \
availSize.w -= size; \
++i; \
} \
@@ -141,10 +144,10 @@ void Box::onResize(ResizeEvent& ev)
prefSize.h -= border().height();
if (align() & HORIZONTAL) {
- LAYOUT_CHILDREN(x, w);
+ LAYOUT_CHILDREN(x, y, w, h);
}
else {
- LAYOUT_CHILDREN(y, h);
+ LAYOUT_CHILDREN(y, x, h, w);
}
}
}
diff --git a/src/ui/button.cpp b/src/ui/button.cpp
index 58380fe8a..b837fcac6 100644
--- a/src/ui/button.cpp
+++ b/src/ui/button.cpp
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -370,9 +370,11 @@ void RadioButton::deselectRadioGroup()
}
}
-void RadioButton::onSelect()
+void RadioButton::onSelect(bool selected)
{
- ButtonBase::onSelect();
+ ButtonBase::onSelect(selected);
+ if (!selected)
+ return;
if (!m_handleSelect)
return;
diff --git a/src/ui/button.h b/src/ui/button.h
index ca528cbb8..82f839784 100644
--- a/src/ui/button.h
+++ b/src/ui/button.h
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -98,7 +98,7 @@ namespace ui {
void deselectRadioGroup();
protected:
- void onSelect() override;
+ void onSelect(bool selected) override;
private:
int m_radioGroup;
diff --git a/src/ui/grid.cpp b/src/ui/grid.cpp
index 2e0f8f054..c338a0bcf 100644
--- a/src/ui/grid.cpp
+++ b/src/ui/grid.cpp
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -191,20 +191,17 @@ void Grid::onResize(ResizeEvent& ev)
void Grid::onSizeHint(SizeHintEvent& ev)
{
- int w, h;
-
- w = h = 0;
-
calculateSize();
// Calculate the total
- sumStripSize(m_colstrip, w);
- sumStripSize(m_rowstrip, h);
+ gfx::Size sz(0, 0);
+ sumStripSize(m_colstrip, sz.w);
+ sumStripSize(m_rowstrip, sz.h);
- w += border().width();
- h += border().height();
+ sz.w += border().width();
+ sz.h += border().height();
- ev.setSizeHint(Size(w, h));
+ ev.setSizeHint(sz);
}
void Grid::onPaint(PaintEvent& ev)
@@ -374,7 +371,6 @@ void Grid::expandStrip(std::vector& colstrip,
else
size = cell->h; // Transposed
}
-
(this->*incCol)(i, size);
}
}
@@ -423,38 +419,40 @@ void Grid::distributeStripSize(std::vector& colstrip,
}
total_req += border_size;
- if (wantmore_count > 0) {
- int extra_total = rect_size - total_req;
- if (extra_total > 0) {
- // If a expandable column-strip was empty (size=0) then we have
- // to reduce the extra_total size because a new child-spacing is
- // added by this column
- for (i=0; i<(int)colstrip.size(); ++i) {
- if ((colstrip[i].size == 0) &&
- (colstrip[i].expand_count == max_expand_count || same_width)) {
- extra_total -= this->childSpacing();
- }
+ int extra_total = (rect_size - total_req);
+
+ // Expand or reduce "expandable" strip
+ if ((wantmore_count > 0) &&
+ ((extra_total > 0 && (max_expand_count > 0 || same_width)) ||
+ (extra_total < 0))) {
+ // If a expandable column-strip was empty (size=0) then we have
+ // to reduce the extra_total size because a new child-spacing is
+ // added by this column
+ for (i=0; i<(int)colstrip.size(); ++i) {
+ if ((colstrip[i].size == 0) &&
+ (colstrip[i].expand_count == max_expand_count || same_width)) {
+ extra_total -= SGN(extra_total)*this->childSpacing();
}
-
- int extra_foreach = extra_total / wantmore_count;
-
- for (i=0; i<(int)colstrip.size(); ++i) {
- if (colstrip[i].expand_count == max_expand_count || same_width) {
- ASSERT(wantmore_count > 0);
-
- colstrip[i].size += extra_foreach;
- extra_total -= extra_foreach;
-
- if (--wantmore_count == 0) {
- colstrip[i].size += extra_total;
- extra_total = 0;
- }
- }
- }
-
- ASSERT(wantmore_count == 0);
- ASSERT(extra_total == 0);
}
+
+ int extra_foreach = extra_total / wantmore_count;
+
+ for (i=0; i<(int)colstrip.size(); ++i) {
+ if (colstrip[i].expand_count == max_expand_count || same_width) {
+ ASSERT(wantmore_count > 0);
+
+ colstrip[i].size += extra_foreach;
+ extra_total -= extra_foreach;
+
+ if (--wantmore_count == 0) {
+ colstrip[i].size += extra_total;
+ extra_total = 0;
+ }
+ }
+ }
+
+ ASSERT(wantmore_count == 0);
+ ASSERT(extra_total == 0);
}
}
diff --git a/src/ui/grid_ui_tests.cpp b/src/ui/grid_ui_tests.cpp
index 6efa37d70..dea892059 100644
--- a/src/ui/grid_ui_tests.cpp
+++ b/src/ui/grid_ui_tests.cpp
@@ -1,11 +1,12 @@
-// Aseprite
-// Copyright (C) 2001-2015 David Capello
+// Aseprite UI Library
+// Copyright (C) 2001-2016 David Capello
//
-// This program is distributed under the terms of
-// the End-User License Agreement for Aseprite.
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
#define TEST_GUI
#include "tests/test.h"
+#include "gfx/rect_io.h"
#include "gfx/size.h"
using namespace gfx;
@@ -144,7 +145,7 @@ TEST(Grid, SameWidth2x1Grid)
// | | |
// +----------------------------+---+
//
-TEST(Grid, Intrincate3x3Grid)
+TEST(Grid, Intrincate2x2Grid)
{
Grid* grid = new Grid(3, false);
Widget* w1 = new Widget;
@@ -226,3 +227,82 @@ TEST(Grid, FourColumns)
EXPECT_EQ(gfx::Rect(30, 0, 10, 10), d.bounds());
EXPECT_EQ(gfx::Rect(0, 10, 40, 10), e.bounds());
}
+
+TEST(Grid, OneFixedReduceThree)
+{
+ Grid grid(1, false);
+ grid.noBorderNoChildSpacing();
+
+ Widget a;
+ Widget b;
+ Widget c;
+ Widget d;
+ a.setMinSize(gfx::Size(10, 10));
+ b.setMinSize(gfx::Size(10, 10));
+ c.setMinSize(gfx::Size(10, 10));
+ d.setMinSize(gfx::Size(10, 10));
+
+ grid.addChildInCell(&a, 1, 1, HORIZONTAL);
+ grid.addChildInCell(&b, 1, 1, HORIZONTAL | VERTICAL);
+ grid.addChildInCell(&c, 1, 1, HORIZONTAL | VERTICAL);
+ grid.addChildInCell(&d, 1, 1, HORIZONTAL | VERTICAL);
+
+ // Test request size
+ grid.setChildSpacing(0);
+ EXPECT_EQ(gfx::Size(10, 40), grid.sizeHint());
+
+ // Test bigger layout
+ grid.setBounds(gfx::Rect(0, 0, 10, 100));
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 10), a.bounds());
+ EXPECT_EQ(gfx::Rect(0, 10, 10, 30), b.bounds());
+ EXPECT_EQ(gfx::Rect(0, 40, 10, 30), c.bounds());
+ EXPECT_EQ(gfx::Rect(0, 70, 10, 30), d.bounds());
+
+ // Test perfect layout
+ grid.setBounds(gfx::Rect(0, 0, 10, 40));
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 10), a.bounds());
+ EXPECT_EQ(gfx::Rect(0, 10, 10, 10), b.bounds());
+ EXPECT_EQ(gfx::Rect(0, 20, 10, 10), c.bounds());
+ EXPECT_EQ(gfx::Rect(0, 30, 10, 10), d.bounds());
+
+ // Test reduced layout
+ grid.setBounds(gfx::Rect(0, 0, 10, 16));
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 10), a.bounds());
+ EXPECT_EQ(gfx::Rect(0, 10, 10, 2), b.bounds());
+ EXPECT_EQ(gfx::Rect(0, 12, 10, 2), c.bounds());
+ EXPECT_EQ(gfx::Rect(0, 14, 10, 2), d.bounds());
+}
+
+TEST(Grid, ReduceThree)
+{
+ Grid grid(1, false);
+ grid.noBorderNoChildSpacing();
+
+ Widget a;
+ Widget b;
+ Widget c;
+ a.setMinSize(gfx::Size(10, 10));
+ b.setMinSize(gfx::Size(10, 10));
+ c.setMinSize(gfx::Size(10, 10));
+
+ grid.addChildInCell(&a, 1, 1, HORIZONTAL);
+ grid.addChildInCell(&b, 1, 1, HORIZONTAL);
+ grid.addChildInCell(&c, 1, 1, HORIZONTAL);
+
+ // Test request size
+ grid.setChildSpacing(0);
+ EXPECT_EQ(gfx::Size(10, 30), grid.sizeHint());
+
+ // Test bigger layout (as these widgets aren't expandible, they
+ // should have height=10)
+ grid.setBounds(gfx::Rect(0, 0, 10, 90));
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 10), a.bounds());
+ EXPECT_EQ(gfx::Rect(0, 10, 10, 10), b.bounds());
+ EXPECT_EQ(gfx::Rect(0, 20, 10, 10), c.bounds());
+
+ // Test reduced layout
+ grid.setBounds(gfx::Rect(0, 0, 10, 12));
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 4), a.bounds());
+ EXPECT_EQ(gfx::Rect(0, 4, 10, 4), b.bounds());
+ EXPECT_EQ(gfx::Rect(0, 8, 10, 4), c.bounds());
+}
diff --git a/src/ui/popup_window.cpp b/src/ui/popup_window.cpp
index 462b056a8..a49791a86 100644
--- a/src/ui/popup_window.cpp
+++ b/src/ui/popup_window.cpp
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -26,6 +26,7 @@ PopupWindow::PopupWindow(const std::string& text,
, m_clickBehavior(clickBehavior)
, m_enterBehavior(enterBehavior)
, m_filtering(false)
+ , m_fixed(false)
{
setSizeable(false);
setMoveable(false);
@@ -64,12 +65,18 @@ void PopupWindow::makeFloating()
{
stopFilteringMessages();
setMoveable(true);
+ m_fixed = false;
+
+ onMakeFloating();
}
void PopupWindow::makeFixed()
{
startFilteringMessages();
setMoveable(false);
+ m_fixed = true;
+
+ onMakeFixed();
}
bool PopupWindow::onProcessMessage(Message* msg)
@@ -91,7 +98,7 @@ bool PopupWindow::onProcessMessage(Message* msg)
break;
case kMouseLeaveMessage:
- if (m_hotRegion.isEmpty() && !isMoveable())
+ if (m_hotRegion.isEmpty() && m_fixed)
closeWindow(nullptr);
break;
@@ -139,7 +146,7 @@ bool PopupWindow::onProcessMessage(Message* msg)
break;
case kMouseMoveMessage:
- if (!isMoveable() &&
+ if (m_fixed &&
!m_hotRegion.isEmpty() &&
manager()->getCapture() == NULL) {
gfx::Point mousePos = static_cast(msg)->position();
@@ -202,19 +209,34 @@ void PopupWindow::onInitTheme(InitThemeEvent& ev)
void PopupWindow::onHitTest(HitTestEvent& ev)
{
+ Window::onHitTest(ev);
+
Widget* picked = manager()->pick(ev.point());
if (picked) {
WidgetType type = picked->type();
- if ((type == kWindowWidget && picked == this) ||
- type == kBoxWidget ||
- type == kLabelWidget ||
- type == kGridWidget ||
- type == kSeparatorWidget) {
- ev.setHit(HitTestCaption);
- return;
+ if (type == kWindowWidget && picked == this) {
+ if (isSizeable() && (ev.hit() == HitTestBorderNW ||
+ ev.hit() == HitTestBorderN ||
+ ev.hit() == HitTestBorderNE ||
+ ev.hit() == HitTestBorderE ||
+ ev.hit() == HitTestBorderSE ||
+ ev.hit() == HitTestBorderS ||
+ ev.hit() == HitTestBorderSW ||
+ ev.hit() == HitTestBorderW)) {
+ // Use the hit value from Window::onHitTest()
+ return;
+ }
+ else {
+ ev.setHit(isMoveable() ? HitTestCaption: HitTestClient);
+ }
+ }
+ else if (type == kBoxWidget ||
+ type == kLabelWidget ||
+ type == kGridWidget ||
+ type == kSeparatorWidget) {
+ ev.setHit(isMoveable() ? HitTestCaption: HitTestClient);
}
}
- Window::onHitTest(ev);
}
void PopupWindow::startFilteringMessages()
@@ -241,4 +263,14 @@ void PopupWindow::stopFilteringMessages()
}
}
+void PopupWindow::onMakeFloating()
+{
+ // Do nothing
+}
+
+void PopupWindow::onMakeFixed()
+{
+ // Do nothing
+}
+
} // namespace ui
diff --git a/src/ui/popup_window.h b/src/ui/popup_window.h
index 1b3750774..4def669fd 100644
--- a/src/ui/popup_window.h
+++ b/src/ui/popup_window.h
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -46,6 +46,9 @@ namespace ui {
void onInitTheme(InitThemeEvent& ev) override;
void onHitTest(HitTestEvent& ev) override;
+ virtual void onMakeFloating();
+ virtual void onMakeFixed();
+
private:
void startFilteringMessages();
void stopFilteringMessages();
@@ -54,6 +57,7 @@ namespace ui {
EnterBehavior m_enterBehavior;
gfx::Region m_hotRegion;
bool m_filtering;
+ bool m_fixed;
};
} // namespace ui
diff --git a/src/ui/widget.cpp b/src/ui/widget.cpp
index 1b9301ec8..56946271d 100644
--- a/src/ui/widget.cpp
+++ b/src/ui/widget.cpp
@@ -211,7 +211,7 @@ void Widget::setEnabled(bool state)
disableFlags(DISABLED);
invalidate();
- onEnable();
+ onEnable(true);
}
}
else {
@@ -221,7 +221,7 @@ void Widget::setEnabled(bool state)
enableFlags(DISABLED);
invalidate();
- onDisable();
+ onEnable(false);
}
}
}
@@ -233,7 +233,7 @@ void Widget::setSelected(bool state)
enableFlags(SELECTED);
invalidate();
- onSelect();
+ onSelect(true);
}
}
else {
@@ -241,7 +241,7 @@ void Widget::setSelected(bool state)
disableFlags(SELECTED);
invalidate();
- onDeselect();
+ onSelect(false);
}
}
}
@@ -1436,22 +1436,12 @@ void Widget::onSetDecorativeWidgetBounds()
}
}
-void Widget::onEnable()
+void Widget::onEnable(bool enabled)
{
// Do nothing
}
-void Widget::onDisable()
-{
- // Do nothing
-}
-
-void Widget::onSelect()
-{
- // Do nothing
-}
-
-void Widget::onDeselect()
+void Widget::onSelect(bool selected)
{
// Do nothing
}
diff --git a/src/ui/widget.h b/src/ui/widget.h
index e7bf33374..54bb886c4 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -368,10 +368,8 @@ namespace ui {
virtual void onBroadcastMouseMessage(WidgetsList& targets);
virtual void onInitTheme(InitThemeEvent& ev);
virtual void onSetDecorativeWidgetBounds();
- virtual void onEnable();
- virtual void onDisable();
- virtual void onSelect();
- virtual void onDeselect();
+ virtual void onEnable(bool enabled);
+ virtual void onSelect(bool selected);
virtual void onSetText();
virtual void onSetBgColor();
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index 09e7b587b..79f4a1f0f 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -182,6 +182,11 @@ void Window::onWindowResize()
// Do nothing
}
+void Window::onWindowMovement()
+{
+ // Do nothing
+}
+
void Window::remapWindow()
{
if (m_isAutoRemap) {
@@ -579,6 +584,8 @@ void Window::moveWindow(const gfx::Rect& rect, bool use_blit)
}
manager->invalidateDisplayRegion(invalidManagerRegion);
+
+ onWindowMovement();
}
} // namespace ui
diff --git a/src/ui/window.h b/src/ui/window.h
index 3f1120544..c64d7ce9e 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -1,5 +1,5 @@
// Aseprite UI Library
-// Copyright (C) 2001-2013, 2015 David Capello
+// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -46,6 +46,7 @@ namespace ui {
bool isDesktop() const { return m_isDesktop; }
bool isOnTop() const { return m_isOnTop; }
bool isWantFocus() const { return m_isWantFocus; }
+ bool isSizeable() const { return m_isSizeable; }
bool isMoveable() const { return m_isMoveable; }
HitTest hitTest(const gfx::Point& point);
@@ -67,6 +68,7 @@ namespace ui {
virtual void onClose(CloseEvent& ev);
virtual void onHitTest(HitTestEvent& ev);
virtual void onWindowResize();
+ virtual void onWindowMovement();
private:
void windowSetPosition(const gfx::Rect& rect);