mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-24 03:40:14 +00:00
Add "Size" options in CanvasSizeCommand to specify width/height
- Added canvas icons to change the expansion direction in CanvasSizeCommand - Added Widget::at() and Widget::offerCapture() member functions - Improved ButtonSet widget
This commit is contained in:
parent
81bfd5da55
commit
d14a0fe075
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -339,6 +339,16 @@
|
||||
<part id="freehand_algo_pixel_perfect_selected" x="168" y="208" w="8" h="8" />
|
||||
<part id="freehand_algo_dots" x="176" y="208" w="8" h="8" />
|
||||
<part id="freehand_algo_dots_selected" x="184" y="208" w="8" h="8" />
|
||||
<part id="canvas_nw" x="96" y="96" w="16" h="16" />
|
||||
<part id="canvas_n" x="112" y="96" w="16" h="16" />
|
||||
<part id="canvas_ne" x="128" y="96" w="16" h="16" />
|
||||
<part id="canvas_w" x="96" y="112" w="16" h="16" />
|
||||
<part id="canvas_c" x="112" y="112" w="16" h="16" />
|
||||
<part id="canvas_e" x="128" y="112" w="16" h="16" />
|
||||
<part id="canvas_sw" x="96" y="128" w="16" h="16" />
|
||||
<part id="canvas_s" x="112" y="128" w="16" h="16" />
|
||||
<part id="canvas_se" x="128" y="128" w="16" h="16" />
|
||||
<part id="canvas_empty" x="96" y="96" w="1" h="1" />
|
||||
</parts>
|
||||
|
||||
<stylesheet>
|
||||
|
@ -1,32 +1,53 @@
|
||||
<!-- ASEPRITE -->
|
||||
<!-- Copyright (C) 2001-2013 by David Capello -->
|
||||
<!-- Copyright (C) 2001-2014 by David Capello -->
|
||||
<gui>
|
||||
<box vertical="true" id="main_box">
|
||||
<box horizontal="true">
|
||||
<box vertical="true" homogeneous="true">
|
||||
<label text="Left:" />
|
||||
<label text="Right:" />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true">
|
||||
<entry text="0" id="left" maxsize="32" maxwidth="64" tooltip="Columns to be added/removed in the left side. Use a negative number to remove columns." />
|
||||
<entry text="0" id="right" maxsize="32" maxwidth="64" tooltip="Columns to be added/removed in the right side. Use a negative number to remove columns." />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true">
|
||||
<label text="Top:" />
|
||||
<label text="Bottom:" />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true">
|
||||
<entry text="0" id="top" maxsize="32" maxwidth="64" tooltip="Rows to be added/removed in the top side. Use a negative number to remove rows." />
|
||||
<entry text="0" id="bottom" maxsize="32" maxwidth="64" tooltip="Rows to be added/removed in the bottom side. Use a negative number to remove rows." />
|
||||
</box>
|
||||
</box>
|
||||
<window text="Canvas Size" id="canvas_size">
|
||||
<vbox>
|
||||
<separator text="Size:" left="true" horizontal="true" />
|
||||
<hbox>
|
||||
<grid columns="2">
|
||||
<label text="Width:" />
|
||||
<entry text="0" id="width" maxsize="32" maxwidth="64" magnet="true" />
|
||||
<label text="Height:" />
|
||||
<entry text="0" id="height" maxsize="32" maxwidth="64" />
|
||||
<hbox filler="true" cell_hspan="2" />
|
||||
</grid>
|
||||
<buttonset columns="3" id="dir">
|
||||
<item icon="canvas_nw" />
|
||||
<item icon="canvas_n" />
|
||||
<item icon="canvas_ne" />
|
||||
<item icon="canvas_w" />
|
||||
<item icon="canvas_c" />
|
||||
<item icon="canvas_e" />
|
||||
<item icon="canvas_sw" />
|
||||
<item icon="canvas_s" />
|
||||
<item icon="canvas_se" />
|
||||
</buttonset>
|
||||
</hbox>
|
||||
|
||||
<separator text="Borders:" left="true" horizontal="true" />
|
||||
<grid columns="4">
|
||||
<label text="Left:" />
|
||||
<entry text="0" id="left" maxsize="32" maxwidth="64" tooltip="Columns to be added/removed in the left side. Use a negative number to remove columns." />
|
||||
|
||||
<label text="Top:" />
|
||||
<entry text="0" id="top" maxsize="32" maxwidth="64" tooltip="Rows to be added/removed in the top side. Use a negative number to remove rows." />
|
||||
|
||||
<label text="Right:" />
|
||||
<entry text="0" id="right" maxsize="32" maxwidth="64" tooltip="Columns to be added/removed in the right side. Use a negative number to remove columns." />
|
||||
|
||||
<label text="Bottom:" />
|
||||
<entry text="0" id="bottom" maxsize="32" maxwidth="64" tooltip="Rows to be added/removed in the bottom side. Use a negative number to remove rows." />
|
||||
</grid>
|
||||
|
||||
<separator horizontal="true" />
|
||||
<box horizontal="true">
|
||||
<box horizontal="true" expansive="true" />
|
||||
<box horizontal="true" homogeneous="true">
|
||||
<hbox>
|
||||
<boxfiller />
|
||||
<hbox homogeneous="true">
|
||||
<button text="&OK" closewindow="true" id="ok" magnet="true" width="60" />
|
||||
<button text="&Cancel" closewindow="true" />
|
||||
</box>
|
||||
</box>
|
||||
</box>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</window>
|
||||
</gui>
|
||||
|
@ -29,9 +29,11 @@
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/settings/settings.h"
|
||||
#include "app/ui/button_set.h"
|
||||
#include "app/ui/color_bar.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/editor/select_box_state.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/undo_transaction.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/unique_ptr.h"
|
||||
@ -40,11 +42,12 @@
|
||||
#include "raster/sprite.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#include <allegro/unicode.h>
|
||||
#include "generated_canvas_size.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
using namespace app::skin;
|
||||
|
||||
// Disable warning about usage of "this" in initializer list.
|
||||
#ifdef _MSC_VER
|
||||
@ -52,82 +55,84 @@ using namespace ui;
|
||||
#endif
|
||||
|
||||
// Window used to show canvas parameters.
|
||||
class CanvasSizeWindow : public Window
|
||||
class CanvasSizeWindow : public app::gen::CanvasSize
|
||||
, public SelectBoxDelegate
|
||||
{
|
||||
public:
|
||||
CanvasSizeWindow(int left, int top, int right, int bottom)
|
||||
: Window(WithTitleBar, "Canvas Size")
|
||||
, m_editor(current_editor)
|
||||
, m_mainBox(app::load_widget<Widget>("canvas_size.xml", "main_box"))
|
||||
, m_left(app::find_widget<Entry>(m_mainBox, "left"))
|
||||
, m_right(app::find_widget<Entry>(m_mainBox, "right"))
|
||||
, m_top(app::find_widget<Entry>(m_mainBox, "top"))
|
||||
, m_bottom(app::find_widget<Entry>(m_mainBox, "bottom"))
|
||||
, m_ok(app::find_widget<Button>(m_mainBox, "ok"))
|
||||
, m_rect(-left, -top,
|
||||
current_editor->sprite()->width() + left + right,
|
||||
current_editor->sprite()->height() + top + bottom)
|
||||
enum class Dir { NW, N, NE, W, C, E, SW, S, SE };
|
||||
|
||||
CanvasSizeWindow()
|
||||
: m_editor(current_editor)
|
||||
, m_rect(0, 0, current_editor->sprite()->width(), current_editor->sprite()->height())
|
||||
, m_selectBoxState(new SelectBoxState(this, m_rect,
|
||||
SelectBoxState::PaintRulers |
|
||||
SelectBoxState::PaintDarkOutside))
|
||||
{
|
||||
addChild(m_mainBox);
|
||||
SelectBoxState::PaintRulers |
|
||||
SelectBoxState::PaintDarkOutside)) {
|
||||
setWidth(m_rect.w);
|
||||
setHeight(m_rect.h);
|
||||
setLeft(0);
|
||||
setRight(0);
|
||||
setTop(0);
|
||||
setBottom(0);
|
||||
|
||||
m_left->setTextf("%d", left);
|
||||
m_right->setTextf("%d", right);
|
||||
m_top->setTextf("%d", top);
|
||||
m_bottom->setTextf("%d", bottom);
|
||||
|
||||
m_left ->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onEntriesChange, this));
|
||||
m_right ->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onEntriesChange, this));
|
||||
m_top ->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onEntriesChange, this));
|
||||
m_bottom->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onEntriesChange, this));
|
||||
width() ->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onSizeChange, this));
|
||||
height()->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onSizeChange, this));
|
||||
dir() ->ItemChange.connect(Bind<void>(&CanvasSizeWindow::onDirChange, this));;
|
||||
left() ->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onBorderChange, this));
|
||||
right() ->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onBorderChange, this));
|
||||
top() ->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onBorderChange, this));
|
||||
bottom()->EntryChange.connect(Bind<void>(&CanvasSizeWindow::onBorderChange, this));
|
||||
|
||||
m_editor->setState(m_selectBoxState);
|
||||
|
||||
dir()->setSelectedItem((int)Dir::C);
|
||||
updateIcons();
|
||||
}
|
||||
|
||||
~CanvasSizeWindow()
|
||||
{
|
||||
~CanvasSizeWindow() {
|
||||
m_editor->backToPreviousState();
|
||||
}
|
||||
|
||||
bool pressedOk() { return getKiller() == m_ok; }
|
||||
bool pressedOk() { return getKiller() == ok(); }
|
||||
|
||||
int getLeft() const { return m_left->getTextInt(); }
|
||||
int getRight() const { return m_right->getTextInt(); }
|
||||
int getTop() const { return m_top->getTextInt(); }
|
||||
int getBottom() const { return m_bottom->getTextInt(); }
|
||||
int getWidth() { return width()->getTextInt(); }
|
||||
int getHeight() { return height()->getTextInt(); }
|
||||
int getLeft() { return left()->getTextInt(); }
|
||||
int getRight() { return right()->getTextInt(); }
|
||||
int getTop() { return top()->getTextInt(); }
|
||||
int getBottom() { return bottom()->getTextInt(); }
|
||||
|
||||
protected:
|
||||
|
||||
// SelectBoxDelegate impleentation
|
||||
virtual void onChangeRectangle(const gfx::Rect& rect) override
|
||||
{
|
||||
virtual void onChangeRectangle(const gfx::Rect& rect) override {
|
||||
m_rect = rect;
|
||||
|
||||
m_left->setTextf("%d", -m_rect.x);
|
||||
m_top->setTextf("%d", -m_rect.y);
|
||||
m_right->setTextf("%d", (m_rect.x + m_rect.w) - current_editor->sprite()->width());
|
||||
m_bottom->setTextf("%d", (m_rect.y + m_rect.h) - current_editor->sprite()->height());
|
||||
updateSizeFromRect();
|
||||
updateBorderFromRect();
|
||||
updateIcons();
|
||||
}
|
||||
|
||||
void onEntriesChange()
|
||||
{
|
||||
int left = getLeft();
|
||||
int top = getTop();
|
||||
|
||||
m_rect = gfx::Rect(-left, -top,
|
||||
m_editor->sprite()->width() + left + getRight(),
|
||||
m_editor->sprite()->height() + top + getBottom());
|
||||
|
||||
static_cast<SelectBoxState*>(m_selectBoxState.get())->setBoxBounds(m_rect);
|
||||
|
||||
// Redraw new rulers position
|
||||
m_editor->invalidate();
|
||||
void onSizeChange() {
|
||||
updateBorderFromSize();
|
||||
updateRectFromBorder();
|
||||
updateEditorBoxFromRect();
|
||||
}
|
||||
|
||||
virtual void onBroadcastMouseMessage(WidgetsList& targets) override
|
||||
{
|
||||
void onDirChange() {
|
||||
updateIcons();
|
||||
updateBorderFromSize();
|
||||
updateRectFromBorder();
|
||||
updateEditorBoxFromRect();
|
||||
}
|
||||
|
||||
void onBorderChange() {
|
||||
updateIcons();
|
||||
updateRectFromBorder();
|
||||
updateSizeFromRect();
|
||||
updateEditorBoxFromRect();
|
||||
}
|
||||
|
||||
virtual void onBroadcastMouseMessage(WidgetsList& targets) override {
|
||||
Window::onBroadcastMouseMessage(targets);
|
||||
|
||||
// Add the editor as receptor of mouse events too.
|
||||
@ -135,13 +140,143 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void updateBorderFromSize() {
|
||||
int w = getWidth() - m_editor->sprite()->width();
|
||||
int h = getHeight() - m_editor->sprite()->height();
|
||||
int l, r, t, b;
|
||||
l = r = t = b = 0;
|
||||
|
||||
switch ((Dir)dir()->selectedItem()) {
|
||||
case Dir::NW:
|
||||
case Dir::W:
|
||||
case Dir::SW:
|
||||
r = w;
|
||||
break;
|
||||
case Dir::N:
|
||||
case Dir::C:
|
||||
case Dir::S:
|
||||
l = r = w/2;
|
||||
if (w & 1)
|
||||
r += (w >= 0 ? 1: -1);
|
||||
break;
|
||||
case Dir::NE:
|
||||
case Dir::E:
|
||||
case Dir::SE:
|
||||
l = w;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((Dir)dir()->selectedItem()) {
|
||||
case Dir::NW:
|
||||
case Dir::N:
|
||||
case Dir::NE:
|
||||
b = h;
|
||||
break;
|
||||
case Dir::W:
|
||||
case Dir::C:
|
||||
case Dir::E:
|
||||
b = t = h/2;
|
||||
if (h & 1)
|
||||
t += (h >= 0 ? 1: -1);
|
||||
break;
|
||||
case Dir::SW:
|
||||
case Dir::S:
|
||||
case Dir::SE:
|
||||
t = h;
|
||||
break;
|
||||
}
|
||||
|
||||
setLeft(l);
|
||||
setRight(r);
|
||||
setTop(t);
|
||||
setBottom(b);
|
||||
}
|
||||
|
||||
void updateRectFromBorder() {
|
||||
int left = getLeft();
|
||||
int top = getTop();
|
||||
|
||||
m_rect = gfx::Rect(-left, -top,
|
||||
m_editor->sprite()->width() + left + getRight(),
|
||||
m_editor->sprite()->height() + top + getBottom());
|
||||
}
|
||||
|
||||
void updateSizeFromRect() {
|
||||
setWidth(m_rect.w);
|
||||
setHeight(m_rect.h);
|
||||
}
|
||||
|
||||
void updateBorderFromRect() {
|
||||
setLeft(-m_rect.x);
|
||||
setTop(-m_rect.y);
|
||||
setRight((m_rect.x + m_rect.w) - current_editor->sprite()->width());
|
||||
setBottom((m_rect.y + m_rect.h) - current_editor->sprite()->height());
|
||||
}
|
||||
|
||||
void updateEditorBoxFromRect() {
|
||||
static_cast<SelectBoxState*>(m_selectBoxState.get())->setBoxBounds(m_rect);
|
||||
|
||||
// Redraw new rulers position
|
||||
m_editor->invalidate();
|
||||
}
|
||||
|
||||
void updateIcons() {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
||||
|
||||
int l = getLeft();
|
||||
int r = getRight();
|
||||
int t = getTop();
|
||||
int b = getBottom();
|
||||
int sel = dir()->selectedItem();
|
||||
|
||||
int c = 0;
|
||||
for (int v=0; v<3; ++v) {
|
||||
for (int u=0; u<3; ++u) {
|
||||
const char* iconId = "canvas_empty";
|
||||
|
||||
if (c == sel) {
|
||||
iconId = "canvas_c";
|
||||
}
|
||||
else if (u+1 < 3 && (u+1)+3*v == sel) {
|
||||
iconId = "canvas_w";
|
||||
}
|
||||
else if (u-1 >= 0 && (u-1)+3*v == sel) {
|
||||
iconId = "canvas_e";
|
||||
}
|
||||
else if (v+1 < 3 && u+3*(v+1) == sel) {
|
||||
iconId = "canvas_n";
|
||||
}
|
||||
else if (v-1 >= 0 && u+3*(v-1) == sel) {
|
||||
iconId = "canvas_s";
|
||||
}
|
||||
else if (u+1 < 3 && v+1 < 3 && (u+1)+3*(v+1) == sel) {
|
||||
iconId = "canvas_nw";
|
||||
}
|
||||
else if (u-1 >= 0 && v+1 < 3 && (u-1)+3*(v+1) == sel) {
|
||||
iconId = "canvas_ne";
|
||||
}
|
||||
else if (u+1 < 3 && v-1 >= 0 && (u+1)+3*(v-1) == sel) {
|
||||
iconId = "canvas_sw";
|
||||
}
|
||||
else if (u-1 >= 0 && v-1 >= 0 && (u-1)+3*(v-1) == sel) {
|
||||
iconId = "canvas_se";
|
||||
}
|
||||
|
||||
dir()->getItem(c)->setIcon(theme->get_part(iconId));
|
||||
++c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setWidth(int v) { width()->setTextf("%d", v); }
|
||||
void setHeight(int v) { height()->setTextf("%d", v); }
|
||||
void setLeft(int v) { left()->setTextf("%d", v); }
|
||||
void setRight(int v) { right()->setTextf("%d", v); }
|
||||
void setTop(int v) { top()->setTextf("%d", v); }
|
||||
void setBottom(int v) { bottom()->setTextf("%d", v); }
|
||||
|
||||
Editor* m_editor;
|
||||
Widget* m_mainBox;
|
||||
Entry* m_left;
|
||||
Entry* m_right;
|
||||
Entry* m_top;
|
||||
Entry* m_bottom;
|
||||
Widget* m_ok;
|
||||
gfx::Rect m_rect;
|
||||
EditorStatePtr m_selectBoxState;
|
||||
};
|
||||
@ -179,7 +314,7 @@ void CanvasSizeCommand::onExecute(Context* context)
|
||||
|
||||
if (context->isUiAvailable()) {
|
||||
// load the window widget
|
||||
base::UniquePtr<CanvasSizeWindow> window(new CanvasSizeWindow(0, 0, 0, 0));
|
||||
base::UniquePtr<CanvasSizeWindow> window(new CanvasSizeWindow());
|
||||
|
||||
window->remapWindow();
|
||||
window->centerWindow();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -20,117 +20,178 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <allegro/unicode.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "app/ui/button_set.h"
|
||||
#include "base/bind.h"
|
||||
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "base/bind.h"
|
||||
#include "gfx/color.h"
|
||||
#include "she/surface.h"
|
||||
#include "ui/box.h"
|
||||
#include "ui/button.h"
|
||||
#include "ui/graphics.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/paint_event.h"
|
||||
#include "ui/preferred_size_event.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/theme.h"
|
||||
#include "ui/widget.h"
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
using namespace app::skin;
|
||||
|
||||
class ButtonSet::Item : public RadioButton
|
||||
WidgetType buttonset_item_type()
|
||||
{
|
||||
public:
|
||||
Item(int index, int radioGroup, int b1, int b2, int b3, int b4)
|
||||
: RadioButton("", radioGroup, kButtonWidget)
|
||||
, m_index(index)
|
||||
{
|
||||
setRadioGroup(radioGroup);
|
||||
setAlign(JI_CENTER | JI_MIDDLE);
|
||||
|
||||
setup_mini_look(this);
|
||||
setup_bevels(this, b1, b2, b3, b4);
|
||||
}
|
||||
|
||||
int getIndex() const { return m_index; }
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
};
|
||||
|
||||
ButtonSet::ButtonSet(int w, int h, int firstSelected, ...)
|
||||
: Box(JI_VERTICAL | JI_HOMOGENEOUS)
|
||||
{
|
||||
Box* hbox = NULL;
|
||||
int x, y, icon;
|
||||
va_list ap;
|
||||
int c = 0;
|
||||
char buf[256];
|
||||
|
||||
va_start(ap, firstSelected);
|
||||
|
||||
this->noBorderNoChildSpacing();
|
||||
|
||||
for (y=0; y<h; y++) {
|
||||
if (w > 1) {
|
||||
hbox = new Box(JI_HORIZONTAL | JI_HOMOGENEOUS);
|
||||
hbox->noBorderNoChildSpacing();
|
||||
}
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
icon = va_arg(ap, int);
|
||||
|
||||
Item* item = new Item(c,
|
||||
(int)(reinterpret_cast<unsigned long>(this) & 0xffffffff),
|
||||
x == 0 && y == 0 ? 2: 0,
|
||||
x == w-1 && y == 0 ? 2: 0,
|
||||
x == 0 && y == h-1 ? 2: 0,
|
||||
x == w-1 && y == h-1 ? 2: 0);
|
||||
|
||||
m_items.push_back(item);
|
||||
|
||||
usprintf(buf, "radio%d", c);
|
||||
item->setId(buf);
|
||||
|
||||
if (icon >= 0)
|
||||
set_gfxicon_to_button(item, icon, icon+1, icon, JI_CENTER | JI_MIDDLE);
|
||||
|
||||
item->Click.connect(Bind<void>(&ButtonSet::onItemChange, this));
|
||||
|
||||
if (c == firstSelected)
|
||||
item->setSelected(true);
|
||||
|
||||
if (hbox)
|
||||
hbox->addChild(item);
|
||||
else
|
||||
this->addChild(item);
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
if (hbox)
|
||||
this->addChild(hbox);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
static WidgetType type = kGenericWidget;
|
||||
if (type == kGenericWidget)
|
||||
type = register_widget_type();
|
||||
return type;
|
||||
}
|
||||
|
||||
int ButtonSet::getSelectedItem() const
|
||||
ButtonSet::Item::Item()
|
||||
: Widget(buttonset_item_type())
|
||||
, m_icon(NULL)
|
||||
{
|
||||
Item* sel = findSelectedItem();
|
||||
}
|
||||
|
||||
if (sel)
|
||||
return sel->getIndex();
|
||||
else
|
||||
return -1;
|
||||
void ButtonSet::Item::setIcon(she::Surface* icon)
|
||||
{
|
||||
m_icon = icon;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
ButtonSet* ButtonSet::Item::buttonSet()
|
||||
{
|
||||
return static_cast<ButtonSet*>(getParent());
|
||||
}
|
||||
|
||||
void ButtonSet::Item::onPaint(ui::PaintEvent& ev)
|
||||
{
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
||||
Graphics* g = ev.getGraphics();
|
||||
gfx::Rect rc = getClientBounds();
|
||||
gfx::Color face;
|
||||
int nw;
|
||||
|
||||
if (!gfx::is_transparent(getBgColor()))
|
||||
g->fillRect(getBgColor(), g->getClipBounds());
|
||||
|
||||
if (isSelected() || hasMouseOver()) {
|
||||
nw = PART_TOOLBUTTON_HOT_NW;
|
||||
face = theme->getColor(ThemeColor::ButtonHotFace);
|
||||
}
|
||||
else {
|
||||
nw = PART_TOOLBUTTON_LAST_NW;
|
||||
face = theme->getColor(ThemeColor::ButtonNormalFace);
|
||||
}
|
||||
|
||||
Grid::Info info = buttonSet()->getChildInfo(this);
|
||||
if (info.col < info.grid_cols-1) rc.w+=1*jguiscale();
|
||||
if (info.row < info.grid_rows-1) rc.h+=3*jguiscale();
|
||||
|
||||
theme->draw_bounds_nw(g, rc, nw, face);
|
||||
|
||||
if (m_icon) {
|
||||
g->drawRgbaSurface(m_icon,
|
||||
rc.x + rc.w/2 - m_icon->width()/2,
|
||||
rc.y + rc.h/2 - m_icon->height()/2);
|
||||
}
|
||||
}
|
||||
|
||||
bool ButtonSet::Item::onProcessMessage(ui::Message* msg)
|
||||
{
|
||||
switch (msg->type()) {
|
||||
|
||||
case ui::kMouseDownMessage:
|
||||
captureMouse();
|
||||
buttonSet()->setSelectedItem(this);
|
||||
buttonSet()->onItemChange();
|
||||
break;
|
||||
|
||||
case ui::kMouseUpMessage:
|
||||
if (hasCapture())
|
||||
releaseMouse();
|
||||
break;
|
||||
|
||||
case ui::kMouseMoveMessage:
|
||||
if (hasCapture()) {
|
||||
if (buttonSet()->m_offerCapture)
|
||||
offerCapture(static_cast<ui::MouseMessage*>(msg), buttonset_item_type());
|
||||
}
|
||||
break;
|
||||
|
||||
case ui::kMouseLeaveMessage:
|
||||
case ui::kMouseEnterMessage:
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
return Widget::onProcessMessage(msg);
|
||||
}
|
||||
|
||||
void ButtonSet::Item::onPreferredSize(ui::PreferredSizeEvent& ev)
|
||||
{
|
||||
gfx::Size sz(16, 16); // TODO Calculate from icon
|
||||
|
||||
Grid::Info info = buttonSet()->getChildInfo(this);
|
||||
if (info.row == info.grid_rows-1)
|
||||
sz.h += 3;
|
||||
|
||||
ev.setPreferredSize(sz*jguiscale());
|
||||
}
|
||||
|
||||
ButtonSet::ButtonSet(int columns)
|
||||
: Grid(columns, false)
|
||||
, m_offerCapture(true)
|
||||
{
|
||||
noBorderNoChildSpacing();
|
||||
}
|
||||
|
||||
void ButtonSet::addItem(she::Surface* icon, int hspan, int vspan)
|
||||
{
|
||||
Item* item = new Item();
|
||||
item->setIcon(icon);
|
||||
addChildInCell(item, hspan, vspan, JI_CENTER | JI_MIDDLE);
|
||||
}
|
||||
|
||||
ButtonSet::Item* ButtonSet::getItem(int index)
|
||||
{
|
||||
return dynamic_cast<Item*>(at(index));
|
||||
}
|
||||
|
||||
int ButtonSet::selectedItem() const
|
||||
{
|
||||
int index = 0;
|
||||
for (Widget* child : getChildren()) {
|
||||
if (child->isSelected())
|
||||
return index;
|
||||
++index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ButtonSet::setSelectedItem(int index)
|
||||
{
|
||||
Item* sel = findSelectedItem();
|
||||
if (sel && sel->getIndex() == index)
|
||||
if (index >= 0 && index < (int)getChildren().size())
|
||||
setSelectedItem(static_cast<Item*>(at(index)));
|
||||
else
|
||||
setSelectedItem(static_cast<Item*>(NULL));
|
||||
}
|
||||
|
||||
void ButtonSet::setSelectedItem(Item* item)
|
||||
{
|
||||
if (item && item->isSelected())
|
||||
return;
|
||||
|
||||
sel->setSelected(false);
|
||||
m_items[index]->setSelected(true);
|
||||
Item* sel = findSelectedItem();
|
||||
if (sel)
|
||||
sel->setSelected(false);
|
||||
|
||||
if (item)
|
||||
item->setSelected(true);
|
||||
}
|
||||
|
||||
void ButtonSet::deselectItems()
|
||||
@ -140,24 +201,23 @@ void ButtonSet::deselectItems()
|
||||
sel->setSelected(false);
|
||||
}
|
||||
|
||||
Widget* ButtonSet::getButtonAt(int index)
|
||||
void ButtonSet::setOfferCapture(bool state)
|
||||
{
|
||||
return m_items[index];
|
||||
}
|
||||
|
||||
ButtonSet::Item* ButtonSet::findSelectedItem() const
|
||||
{
|
||||
for (Items::const_iterator it=m_items.begin(), end=m_items.end();
|
||||
it != end; ++it) {
|
||||
if ((*it)->isSelected())
|
||||
return *it;
|
||||
}
|
||||
return NULL;
|
||||
m_offerCapture = state;
|
||||
}
|
||||
|
||||
void ButtonSet::onItemChange()
|
||||
{
|
||||
ItemChange();
|
||||
}
|
||||
|
||||
ButtonSet::Item* ButtonSet::findSelectedItem() const
|
||||
{
|
||||
for (Widget* child : getChildren()) {
|
||||
if (child->isSelected())
|
||||
return static_cast<Item*>(child);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -21,22 +21,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/signal.h"
|
||||
#include "ui/box.h"
|
||||
#include "ui/grid.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace app {
|
||||
|
||||
class ButtonSet : public ui::Box {
|
||||
class Item;
|
||||
typedef std::vector<Item*> Items;
|
||||
|
||||
class ButtonSet : public ui::Grid {
|
||||
public:
|
||||
ButtonSet(int w, int h, int firstSelected, ...);
|
||||
class Item : public ui::Widget {
|
||||
public:
|
||||
Item();
|
||||
void setIcon(she::Surface* icon);
|
||||
ButtonSet* buttonSet();
|
||||
protected:
|
||||
void onPaint(ui::PaintEvent& ev) override;
|
||||
bool onProcessMessage(ui::Message* msg) override;
|
||||
void onPreferredSize(ui::PreferredSizeEvent& ev) override;
|
||||
private:
|
||||
she::Surface* m_icon;
|
||||
};
|
||||
|
||||
int getSelectedItem() const;
|
||||
ButtonSet(int columns);
|
||||
|
||||
void addItem(she::Surface* icon, int hspan = 1, int vspan = 1);
|
||||
Item* getItem(int index);
|
||||
|
||||
int selectedItem() const;
|
||||
void setSelectedItem(int index);
|
||||
void setSelectedItem(Item* item);
|
||||
void deselectItems();
|
||||
|
||||
ui::Widget* getButtonAt(int index);
|
||||
void setOfferCapture(bool state);
|
||||
|
||||
Signal0<void> ItemChange;
|
||||
|
||||
@ -46,7 +62,7 @@ namespace app {
|
||||
private:
|
||||
Item* findSelectedItem() const;
|
||||
|
||||
Items m_items;
|
||||
bool m_offerCapture;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -63,24 +63,21 @@ using namespace gfx;
|
||||
using namespace ui;
|
||||
using namespace tools;
|
||||
|
||||
class ContextBar::BrushTypeField : public Button
|
||||
, public IButtonIcon {
|
||||
class ContextBar::BrushTypeField : public ButtonSet {
|
||||
public:
|
||||
BrushTypeField()
|
||||
: Button("")
|
||||
: ButtonSet(1)
|
||||
, m_popupWindow(NULL)
|
||||
, m_brushTypeButton(NULL) {
|
||||
setup_mini_look(this);
|
||||
setIconInterface(this);
|
||||
|
||||
m_bitmap = she::instance()->createRgbaSurface(8, 8);
|
||||
she::ScopedSurfaceLock lock(m_bitmap);
|
||||
lock->clear();
|
||||
|
||||
addItem(m_bitmap);
|
||||
}
|
||||
|
||||
~BrushTypeField() {
|
||||
closePopup();
|
||||
setIconInterface(NULL);
|
||||
|
||||
m_bitmap->dispose();
|
||||
}
|
||||
@ -105,43 +102,12 @@ public:
|
||||
convert_image_to_surface(image, palette, m_bitmap,
|
||||
0, 0, 0, 0, image->width(), image->height());
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
// IButtonIcon implementation
|
||||
void destroy() override {
|
||||
// Do nothing, BrushTypeField is added as a widget in the
|
||||
// ContextBar, so it will be destroyed together with the
|
||||
// ContextBar.
|
||||
}
|
||||
|
||||
int getWidth() override {
|
||||
return m_bitmap->width();
|
||||
}
|
||||
|
||||
int getHeight() override {
|
||||
return m_bitmap->height();
|
||||
}
|
||||
|
||||
she::Surface* getNormalIcon() override {
|
||||
return m_bitmap;
|
||||
}
|
||||
|
||||
she::Surface* getSelectedIcon() override {
|
||||
return m_bitmap;
|
||||
}
|
||||
|
||||
she::Surface* getDisabledIcon() override {
|
||||
return m_bitmap;
|
||||
}
|
||||
|
||||
int getIconAlign() override {
|
||||
return JI_CENTER | JI_MIDDLE;
|
||||
getItem(0)->setIcon(m_bitmap);
|
||||
}
|
||||
|
||||
protected:
|
||||
void onClick(Event& ev) override {
|
||||
Button::onClick(ev);
|
||||
void onItemChange() override {
|
||||
ButtonSet::onItemChange();
|
||||
|
||||
if (!m_popupWindow || !m_popupWindow->isVisible())
|
||||
openPopup();
|
||||
@ -150,27 +116,30 @@ protected:
|
||||
}
|
||||
|
||||
void onPreferredSize(PreferredSizeEvent& ev) {
|
||||
ev.setPreferredSize(Size(16*jguiscale(),
|
||||
16*jguiscale()));
|
||||
ev.setPreferredSize(Size(16, 18)*jguiscale());
|
||||
}
|
||||
|
||||
private:
|
||||
void openPopup() {
|
||||
Border border = Border(2, 2, 2, 3)*jguiscale();
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
||||
|
||||
Rect rc = getBounds();
|
||||
rc.y += rc.h;
|
||||
rc.y += rc.h - 2*jguiscale();
|
||||
rc.setSize(getPreferredSize());
|
||||
rc.w *= 3;
|
||||
m_popupWindow = new PopupWindow("", PopupWindow::kCloseOnClickInOtherWindow);
|
||||
m_popupWindow->setAutoRemap(false);
|
||||
m_popupWindow->setBorder(border);
|
||||
m_popupWindow->setBounds(rc + border);
|
||||
m_popupWindow->setBorder(Border(0));
|
||||
m_popupWindow->setBounds(rc);
|
||||
m_popupWindow->child_spacing = 0;
|
||||
|
||||
Region rgn(m_popupWindow->getBounds().createUnion(getBounds()));
|
||||
m_popupWindow->setHotRegion(rgn);
|
||||
m_brushTypeButton = new ButtonSet(3, 1, m_brushType,
|
||||
PART_BRUSH_CIRCLE,
|
||||
PART_BRUSH_SQUARE,
|
||||
PART_BRUSH_LINE);
|
||||
m_brushTypeButton = new ButtonSet(3);
|
||||
m_brushTypeButton->addItem(theme->get_part(PART_BRUSH_CIRCLE));
|
||||
m_brushTypeButton->addItem(theme->get_part(PART_BRUSH_SQUARE));
|
||||
m_brushTypeButton->addItem(theme->get_part(PART_BRUSH_LINE));
|
||||
m_brushTypeButton->setSelectedItem(m_brushType);
|
||||
m_brushTypeButton->ItemChange.connect(&BrushTypeField::onBrushTypeChange, this);
|
||||
m_brushTypeButton->setTransparent(true);
|
||||
m_brushTypeButton->setBgColor(gfx::ColorNone);
|
||||
@ -189,7 +158,7 @@ private:
|
||||
}
|
||||
|
||||
void onBrushTypeChange() {
|
||||
m_brushType = (BrushType)m_brushTypeButton->getSelectedItem();
|
||||
m_brushType = (BrushType)m_brushTypeButton->selectedItem();
|
||||
|
||||
ISettings* settings = UIContext::instance()->settings();
|
||||
Tool* currentTool = settings->getCurrentTool();
|
||||
@ -550,12 +519,13 @@ protected:
|
||||
}
|
||||
|
||||
void onPreferredSize(PreferredSizeEvent& ev) {
|
||||
ev.setPreferredSize(Size(16*jguiscale(),
|
||||
16*jguiscale()));
|
||||
ev.setPreferredSize(Size(16, 18)*jguiscale());
|
||||
}
|
||||
|
||||
private:
|
||||
void openPopup() {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
||||
|
||||
Border border = Border(2, 2, 2, 3)*jguiscale();
|
||||
Rect rc = getBounds();
|
||||
rc.y += rc.h;
|
||||
@ -567,17 +537,18 @@ private:
|
||||
|
||||
Region rgn(m_popupWindow->getBounds().createUnion(getBounds()));
|
||||
m_popupWindow->setHotRegion(rgn);
|
||||
m_freehandAlgoButton = new ButtonSet(3, 1, m_freehandAlgo,
|
||||
PART_FREEHAND_ALGO_DEFAULT,
|
||||
PART_FREEHAND_ALGO_PIXEL_PERFECT,
|
||||
PART_FREEHAND_ALGO_DOTS);
|
||||
m_freehandAlgoButton = new ButtonSet(3);
|
||||
m_freehandAlgoButton->addItem(theme->get_part(PART_FREEHAND_ALGO_DEFAULT));
|
||||
m_freehandAlgoButton->addItem(theme->get_part(PART_FREEHAND_ALGO_PIXEL_PERFECT));
|
||||
m_freehandAlgoButton->addItem(theme->get_part(PART_FREEHAND_ALGO_DOTS));
|
||||
m_freehandAlgoButton->setSelectedItem((int)m_freehandAlgo);
|
||||
m_freehandAlgoButton->ItemChange.connect(&FreehandAlgorithmField::onFreehandAlgoChange, this);
|
||||
m_freehandAlgoButton->setTransparent(true);
|
||||
m_freehandAlgoButton->setBgColor(gfx::ColorNone);
|
||||
|
||||
m_tooltipManager->addTooltipFor(m_freehandAlgoButton->getButtonAt(0), "Normal trace", JI_TOP);
|
||||
m_tooltipManager->addTooltipFor(m_freehandAlgoButton->getButtonAt(1), "Pixel-perfect trace", JI_TOP);
|
||||
m_tooltipManager->addTooltipFor(m_freehandAlgoButton->getButtonAt(2), "Dots", JI_TOP);
|
||||
m_tooltipManager->addTooltipFor(at(0), "Normal trace", JI_TOP);
|
||||
m_tooltipManager->addTooltipFor(at(1), "Pixel-perfect trace", JI_TOP);
|
||||
m_tooltipManager->addTooltipFor(at(2), "Dots", JI_TOP);
|
||||
|
||||
m_popupWindow->addChild(m_freehandAlgoButton);
|
||||
m_popupWindow->openWindow();
|
||||
@ -657,19 +628,22 @@ protected:
|
||||
class ContextBar::SelectionModeField : public ButtonSet
|
||||
{
|
||||
public:
|
||||
SelectionModeField() : ButtonSet(3, 1, 0,
|
||||
PART_SELECTION_REPLACE,
|
||||
PART_SELECTION_ADD,
|
||||
PART_SELECTION_SUBTRACT) {
|
||||
SelectionModeField() : ButtonSet(3) {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
||||
|
||||
addItem(theme->get_part(PART_SELECTION_REPLACE));
|
||||
addItem(theme->get_part(PART_SELECTION_ADD));
|
||||
addItem(theme->get_part(PART_SELECTION_SUBTRACT));
|
||||
|
||||
setSelectedItem(
|
||||
(int)UIContext::instance()->settings()
|
||||
->selection()->getSelectionMode());
|
||||
}
|
||||
|
||||
void setupTooltips(TooltipManager* tooltipManager) {
|
||||
tooltipManager->addTooltipFor(getButtonAt(0), "Replace selection", JI_BOTTOM);
|
||||
tooltipManager->addTooltipFor(getButtonAt(1), "Add to selection (Shift key)", JI_BOTTOM);
|
||||
tooltipManager->addTooltipFor(getButtonAt(2), "Subtract from selection (Alt key)", JI_BOTTOM);
|
||||
tooltipManager->addTooltipFor(at(0), "Replace selection", JI_BOTTOM);
|
||||
tooltipManager->addTooltipFor(at(1), "Add to selection (Shift key)", JI_BOTTOM);
|
||||
tooltipManager->addTooltipFor(at(2), "Subtract from selection (Alt key)", JI_BOTTOM);
|
||||
}
|
||||
|
||||
void setSelectionMode(SelectionMode mode) {
|
||||
@ -681,23 +655,25 @@ protected:
|
||||
void onItemChange() override {
|
||||
ButtonSet::onItemChange();
|
||||
|
||||
int item = getSelectedItem();
|
||||
UIContext::instance()->settings()->selection()
|
||||
->setSelectionMode((SelectionMode)item);
|
||||
->setSelectionMode((SelectionMode)selectedItem());
|
||||
}
|
||||
};
|
||||
|
||||
class ContextBar::DropPixelsField : public ButtonSet
|
||||
{
|
||||
public:
|
||||
DropPixelsField() : ButtonSet(2, 1, -1,
|
||||
PART_DROP_PIXELS_OK,
|
||||
PART_DROP_PIXELS_CANCEL) {
|
||||
DropPixelsField() : ButtonSet(2) {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(getTheme());
|
||||
|
||||
addItem(theme->get_part(PART_DROP_PIXELS_OK));
|
||||
addItem(theme->get_part(PART_DROP_PIXELS_CANCEL));
|
||||
setOfferCapture(false);
|
||||
}
|
||||
|
||||
void setupTooltips(TooltipManager* tooltipManager) {
|
||||
tooltipManager->addTooltipFor(getButtonAt(0), "Drop pixels here", JI_BOTTOM);
|
||||
tooltipManager->addTooltipFor(getButtonAt(1), "Cancel drag and drop", JI_BOTTOM);
|
||||
tooltipManager->addTooltipFor(at(0), "Drop pixels here", JI_BOTTOM);
|
||||
tooltipManager->addTooltipFor(at(1), "Cancel drag and drop", JI_BOTTOM);
|
||||
}
|
||||
|
||||
Signal1<void, ContextBarObserver::DropAction> DropPixels;
|
||||
@ -706,7 +682,7 @@ protected:
|
||||
void onItemChange() override {
|
||||
ButtonSet::onItemChange();
|
||||
|
||||
switch (getSelectedItem()) {
|
||||
switch (selectedItem()) {
|
||||
case 0: DropPixels(ContextBarObserver::DropPixels); break;
|
||||
case 1: DropPixels(ContextBarObserver::CancelDrag); break;
|
||||
}
|
||||
|
@ -1847,6 +1847,11 @@ void SkinTheme::paintTooltip(PaintEvent& ev)
|
||||
g->drawAlignedUIString(widget->getText(), fg, bg, rc, widget->getAlign());
|
||||
}
|
||||
|
||||
she::Surface* SkinTheme::get_part(const std::string& id) const
|
||||
{
|
||||
return get_part_by_id(id)->getBitmap(0);
|
||||
}
|
||||
|
||||
gfx::Color SkinTheme::getWidgetBgColor(Widget* widget)
|
||||
{
|
||||
gfx::Color c = widget->getBgColor();
|
||||
|
@ -160,6 +160,7 @@ namespace app {
|
||||
int get_button_selected_offset() const { return 0; } // TODO Configurable in xml
|
||||
|
||||
she::Surface* get_part(int part_i) const { return m_part[part_i]; }
|
||||
she::Surface* get_part(const std::string& id) const;
|
||||
she::Surface* get_toolicon(const char* tool_id) const;
|
||||
gfx::Size get_part_size(int part_i) const;
|
||||
|
||||
|
@ -24,10 +24,12 @@
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/xml_document.h"
|
||||
#include "app/resource_finder.h"
|
||||
#include "app/ui/button_set.h"
|
||||
#include "app/ui/color_button.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/widget_not_found.h"
|
||||
#include "app/xml_document.h"
|
||||
#include "app/xml_exception.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/fs.h"
|
||||
@ -44,9 +46,11 @@
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
using namespace app::skin;
|
||||
|
||||
static int convert_align_value_to_flags(const char *value);
|
||||
static bool bool_attr_is_true(const TiXmlElement* elem, const char* attribute_name);
|
||||
static int int_attr(const TiXmlElement* elem, const char* attribute_name, int default_value);
|
||||
|
||||
WidgetLoader::WidgetLoader()
|
||||
: m_tooltipManager(NULL)
|
||||
@ -105,7 +109,7 @@ Widget* WidgetLoader::loadWidgetFromXmlFile(
|
||||
const char* nodename = xmlElement->Attribute("id");
|
||||
|
||||
if (nodename && nodename == widgetId) {
|
||||
widget = convertXmlElementToWidget(xmlElement, NULL, widget);
|
||||
widget = convertXmlElementToWidget(xmlElement, NULL, NULL, widget);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -115,7 +119,7 @@ Widget* WidgetLoader::loadWidgetFromXmlFile(
|
||||
return widget;
|
||||
}
|
||||
|
||||
Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget* root, Widget* widget)
|
||||
Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget* root, Widget* parent, Widget* widget)
|
||||
{
|
||||
const std::string elem_name = elem->Value();
|
||||
|
||||
@ -413,6 +417,29 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
|
||||
if (!widget)
|
||||
widget = new ColorButton(Color::fromMask(), app_get_current_pixel_format());
|
||||
}
|
||||
else if (elem_name == "buttonset") {
|
||||
const char* columns = elem->Attribute("columns");
|
||||
|
||||
if (!widget && columns)
|
||||
widget = new ButtonSet(strtol(columns, NULL, 10));
|
||||
}
|
||||
else if (elem_name == "item") {
|
||||
if (!parent)
|
||||
throw std::runtime_error("<item> without parent");
|
||||
|
||||
if (ButtonSet* buttonset = dynamic_cast<ButtonSet*>(parent)) {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(parent->getTheme());
|
||||
|
||||
const char* icon = elem->Attribute("icon");
|
||||
if (icon) {
|
||||
int hspan = int_attr(elem, "hspan", 1);
|
||||
int vspan = int_attr(elem, "vspan", 1);
|
||||
|
||||
she::Surface* sur = theme->get_part(std::string(icon));
|
||||
buttonset->addItem(sur, hspan, vspan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Was the widget created?
|
||||
if (widget)
|
||||
@ -421,7 +448,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
|
||||
return widget;
|
||||
}
|
||||
|
||||
void WidgetLoader::fillWidgetWithXmlElementAttributes(const TiXmlElement* elem, ui::Widget* root, ui::Widget* widget)
|
||||
void WidgetLoader::fillWidgetWithXmlElementAttributes(const TiXmlElement* elem, Widget* root, Widget* widget)
|
||||
{
|
||||
const char* id = elem->Attribute("id");
|
||||
const char* text = elem->Attribute("text");
|
||||
@ -505,7 +532,7 @@ void WidgetLoader::fillWidgetWithXmlElementAttributes(const TiXmlElement* elem,
|
||||
// Children
|
||||
const TiXmlElement* childElem = elem->FirstChildElement();
|
||||
while (childElem) {
|
||||
Widget* child = convertXmlElementToWidget(childElem, root, NULL);
|
||||
Widget* child = convertXmlElementToWidget(childElem, root, widget, NULL);
|
||||
if (child) {
|
||||
// Attach the child in the view
|
||||
if (widget->type == kViewWidget) {
|
||||
@ -587,4 +614,11 @@ static bool bool_attr_is_true(const TiXmlElement* elem, const char* attribute_na
|
||||
return (value != NULL) && (strcmp(value, "true") == 0);
|
||||
}
|
||||
|
||||
static int int_attr(const TiXmlElement* elem, const char* attribute_name, int default_value)
|
||||
{
|
||||
const char* value = elem->Attribute(attribute_name);
|
||||
|
||||
return (value ? strtol(value, NULL, 10): default_value);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -73,7 +73,7 @@ namespace app {
|
||||
const std::string& widgetId,
|
||||
ui::Widget* widget);
|
||||
|
||||
ui::Widget* convertXmlElementToWidget(const TiXmlElement* elem, ui::Widget* root, ui::Widget* widget);
|
||||
ui::Widget* convertXmlElementToWidget(const TiXmlElement* elem, ui::Widget* root, ui::Widget* parent, ui::Widget* widget);
|
||||
void fillWidgetWithXmlElementAttributes(const TiXmlElement* elem, ui::Widget* root, ui::Widget* widget);
|
||||
|
||||
typedef std::map<std::string, IWidgetTypeCreator*> TypeCreatorsMap;
|
||||
|
@ -69,6 +69,7 @@ static std::string convert_type(const std::string& name)
|
||||
{
|
||||
if (name == "box") return "ui::Box";
|
||||
if (name == "button") return "ui::Button";
|
||||
if (name == "buttonset") return "app::ButtonSet";
|
||||
if (name == "check") return "ui::CheckBox";
|
||||
if (name == "combobox") return "ui::ComboBox";
|
||||
if (name == "entry") return "ui::Entry";
|
||||
|
@ -96,6 +96,27 @@ void Grid::addChildInCell(Widget* child, int hspan, int vspan, int align)
|
||||
}
|
||||
}
|
||||
|
||||
Grid::Info Grid::getChildInfo(Widget* child)
|
||||
{
|
||||
Info info;
|
||||
for (int row=0; row<(int)m_rowstrip.size(); ++row) {
|
||||
for (int col=0; col<(int)m_colstrip.size(); ++col) {
|
||||
Cell* cell = m_cells[row][col];
|
||||
|
||||
if (cell->child == child) {
|
||||
info.col = col;
|
||||
info.row = row;
|
||||
info.hspan = cell->hspan;
|
||||
info.vspan = cell->vspan;
|
||||
info.grid_cols = m_colstrip.size();
|
||||
info.grid_rows = m_rowstrip.size();
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void Grid::onResize(ResizeEvent& ev)
|
||||
{
|
||||
gfx::Rect rect = ev.getBounds();
|
||||
@ -151,6 +172,11 @@ void Grid::onResize(ResizeEvent& ev)
|
||||
h = reqSize.h;
|
||||
}
|
||||
|
||||
if (x+w > rect.x+rect.w-this->border_width.r)
|
||||
w = rect.x+rect.w-this->border_width.r-x;
|
||||
if (y+h > rect.y+rect.h-this->border_width.b)
|
||||
h = rect.y+rect.h-this->border_width.b-y;
|
||||
|
||||
cell->child->setBounds(Rect(x, y, w, h));
|
||||
}
|
||||
|
||||
|
@ -14,13 +14,23 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
class Grid : public Widget
|
||||
{
|
||||
class Grid : public Widget {
|
||||
public:
|
||||
struct Info {
|
||||
int col, row;
|
||||
int hspan, vspan;
|
||||
int grid_cols, grid_rows;
|
||||
Info() : col(0), row(0),
|
||||
hspan(0), vspan(0),
|
||||
grid_cols(0), grid_rows(0) {
|
||||
}
|
||||
};
|
||||
|
||||
Grid(int columns, bool same_width_columns);
|
||||
~Grid();
|
||||
|
||||
void addChildInCell(Widget* child, int hspan, int vspan, int align);
|
||||
Info getChildInfo(Widget* child);
|
||||
|
||||
protected:
|
||||
// Events
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013 David Capello
|
||||
// Copyright (C) 2001-2014 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -1237,6 +1237,23 @@ void Widget::releaseMouse()
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::offerCapture(ui::MouseMessage* mouseMsg, int widget_type)
|
||||
{
|
||||
if (hasCapture()) {
|
||||
Widget* pick = getManager()->pick(mouseMsg->position());
|
||||
if (pick && pick->getType() == widget_type) {
|
||||
releaseMouse();
|
||||
|
||||
MouseMessage* mouseMsg2 = new MouseMessage(
|
||||
kMouseDownMessage,
|
||||
mouseMsg->buttons(),
|
||||
mouseMsg->position());
|
||||
mouseMsg2->addRecipient(pick);
|
||||
getManager()->enqueueMessage(mouseMsg2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::hasFocus()
|
||||
{
|
||||
return (this->flags & JI_HASFOCUS) ? true: false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013 David Capello
|
||||
// Copyright (C) 2001-2014 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -34,6 +34,7 @@ namespace ui {
|
||||
class LoadLayoutEvent;
|
||||
class Manager;
|
||||
class Message;
|
||||
class MouseMessage;
|
||||
class PaintEvent;
|
||||
class PreferredSizeEvent;
|
||||
class ResizeEvent;
|
||||
@ -180,6 +181,8 @@ namespace ui {
|
||||
// Returns a list of children.
|
||||
const WidgetsList& getChildren() const { return m_children; }
|
||||
|
||||
Widget* at(int index) { return m_children[index]; }
|
||||
|
||||
// Returns the first/last child or NULL if it doesn't exist.
|
||||
Widget* getFirstChild() {
|
||||
return (!m_children.empty() ? m_children.front(): NULL);
|
||||
@ -332,11 +335,15 @@ namespace ui {
|
||||
void releaseFocus();
|
||||
void captureMouse();
|
||||
void releaseMouse();
|
||||
|
||||
bool hasFocus();
|
||||
bool hasMouse();
|
||||
bool hasMouseOver();
|
||||
bool hasCapture();
|
||||
|
||||
// Offer the capture to widgets of the given type
|
||||
void offerCapture(ui::MouseMessage* mouseMsg, int widget_type);
|
||||
|
||||
// Returns lower-case letter that represet the mnemonic of the widget
|
||||
// (the underscored character, i.e. the letter after & symbol).
|
||||
int getMnemonicChar() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user