Add a "pin" in color selectors to make the popup window floating.

+ Added Frame::hitTest() and Frame::onHitTest().
+ Added LookType enum for SkinProperty.
This commit is contained in:
David Capello 2011-03-29 21:07:37 -03:00
parent 236ee6bb7b
commit 3ad44e3004
21 changed files with 486 additions and 270 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -168,6 +168,8 @@
<part id="layer_editable_selected" x="144" y="184" w="8" h="8" />
<part id="layer_locked" x="160" y="176" w="8" h="8" />
<part id="layer_locked_selected" x="160" y="184" w="8" h="8" />
<part id="unpinned" x="192" y="144" w="8" h="8" />
<part id="pinned" x="200" y="144" w="8" h="8" />
</parts>
</skin>

View File

@ -287,6 +287,7 @@ add_library(aseprite-library
widgets/hex_color_entry.cpp
widgets/menuitem.cpp
widgets/palette_view.cpp
widgets/popup_frame_pin.cpp
widgets/statebar.cpp
widgets/tabs.cpp
widgets/toolbar.cpp)

View File

@ -5,7 +5,6 @@
// read LICENSE.txt for more information.
#define REDRAW_MOVEMENT
#define MOTION_CURSOR JI_CURSOR_NORMAL
#include "config.h"
@ -86,6 +85,81 @@ void Frame::set_wantfocus(bool state)
m_is_wantfocus = state;
}
HitTest Frame::hitTest(const gfx::Point& point)
{
HitTestEvent ev(this, point, HitTestNowhere);
onHitTest(ev);
return ev.getHit();
}
void Frame::onHitTest(HitTestEvent& ev)
{
HitTest ht = HitTestNowhere;
if (!m_is_moveable) {
ev.setHit(ht);
return;
}
int x = ev.getPoint().x;
int y = ev.getPoint().y;
JRect pos = jwidget_get_rect(this);
JRect cpos = jwidget_get_child_rect(this);
// Move
if ((this->hasText())
&& (((x >= cpos->x1) &&
(x < cpos->x2) &&
(y >= pos->y1+this->border_width.b) &&
(y < cpos->y1)))) {
ht = HitTestCaption;
}
// Resize
else if (m_is_sizeable) {
if ((x >= pos->x1) && (x < cpos->x1)) {
if ((y >= pos->y1) && (y < cpos->y1))
ht = HitTestBorderNW;
else if ((y > cpos->y2-1) && (y <= pos->y2-1))
ht = HitTestBorderSW;
else
ht = HitTestBorderW;
}
else if ((y >= pos->y1) && (y < cpos->y1)) {
if ((x >= pos->x1) && (x < cpos->x1))
ht = HitTestBorderNW;
else if ((x > cpos->x2-1) && (x <= pos->x2-1))
ht = HitTestBorderNE;
else
ht = HitTestBorderN;
}
else if ((x > cpos->x2-1) && (x <= pos->x2-1)) {
if ((y >= pos->y1) && (y < cpos->y1))
ht = HitTestBorderNE;
else if ((y > cpos->y2-1) && (y <= pos->y2-1))
ht = HitTestBorderSE;
else
ht = HitTestBorderE;
}
else if ((y > cpos->y2-1) && (y <= pos->y2-1)) {
if ((x >= pos->x1) && (x < cpos->x1))
ht = HitTestBorderSW;
else if ((x > cpos->x2-1) && (x <= pos->x2-1))
ht = HitTestBorderSE;
else
ht = HitTestBorderS;
}
}
else {
// Client area
ht = HitTestClient;
}
jrect_free(pos);
jrect_free(cpos);
ev.setHit(ht);
}
void Frame::remap_window()
{
Size reqSize;
@ -186,26 +260,6 @@ bool Frame::is_toplevel()
return false;
}
bool Frame::is_foreground() const
{
return m_is_foreground;
}
bool Frame::is_desktop() const
{
return m_is_desktop;
}
bool Frame::is_ontop() const
{
return m_is_ontop;
}
bool Frame::is_wantfocus() const
{
return m_is_wantfocus;
}
bool Frame::onProcessMessage(JMessage msg)
{
switch (msg->type) {
@ -237,9 +291,10 @@ bool Frame::onProcessMessage(JMessage msg)
press_x = msg->mouse.x;
press_y = msg->mouse.y;
m_windowAction = this->get_action(press_x, press_y);
m_hitTest = hitTest(gfx::Point(press_x, press_y));
if (m_windowAction != WINDOW_NONE) {
if (m_hitTest != HitTestNowhere &&
m_hitTest != HitTestClient) {
if (click_pos == NULL)
click_pos = jrect_new_copy(this->rc);
else
@ -262,7 +317,7 @@ bool Frame::onProcessMessage(JMessage msg)
click_pos = NULL;
}
m_windowAction = WINDOW_NONE;
m_hitTest = HitTestNowhere;
return true;
}
break;
@ -274,7 +329,7 @@ bool Frame::onProcessMessage(JMessage msg)
// Does it have the mouse captured?
if (hasCapture()) {
// Reposition/resize
if (m_windowAction == WINDOW_MOVE) {
if (m_hitTest == HitTestCaption) {
int x = click_pos->x1 + (msg->mouse.x - press_x);
int y = click_pos->y1 + (msg->mouse.y - press_y);
JRect rect = jrect_new(x, y,
@ -289,26 +344,43 @@ bool Frame::onProcessMessage(JMessage msg)
w = jrect_w(click_pos);
h = jrect_h(click_pos);
if (m_windowAction & WINDOW_RESIZE_LEFT)
w += press_x - msg->mouse.x;
else if (m_windowAction & WINDOW_RESIZE_RIGHT)
w += msg->mouse.x - press_x;
bool hitLeft = (m_hitTest == HitTestBorderNW ||
m_hitTest == HitTestBorderW ||
m_hitTest == HitTestBorderSW);
bool hitTop = (m_hitTest == HitTestBorderNW ||
m_hitTest == HitTestBorderN ||
m_hitTest == HitTestBorderNE);
bool hitRight = (m_hitTest == HitTestBorderNE ||
m_hitTest == HitTestBorderE ||
m_hitTest == HitTestBorderSE);
bool hitBottom = (m_hitTest == HitTestBorderSW ||
m_hitTest == HitTestBorderS ||
m_hitTest == HitTestBorderSE);
if (m_windowAction & WINDOW_RESIZE_TOP)
if (hitLeft) {
w += press_x - msg->mouse.x;
}
else if (hitRight) {
w += msg->mouse.x - press_x;
}
if (hitTop) {
h += (press_y - msg->mouse.y);
else if (m_windowAction & WINDOW_RESIZE_BOTTOM)
}
else if (hitBottom) {
h += (msg->mouse.y - press_y);
}
this->limit_size(&w, &h);
if ((jrect_w(this->rc) != w) ||
(jrect_h(this->rc) != h)) {
if (m_windowAction & WINDOW_RESIZE_LEFT)
if (hitLeft)
x = click_pos->x1 - (w - jrect_w(click_pos));
else
x = this->rc->x1;
if (m_windowAction & WINDOW_RESIZE_TOP)
if (hitTop)
y = click_pos->y1 - (h - jrect_h(click_pos));
else
y = this->rc->y1;
@ -324,44 +396,52 @@ bool Frame::onProcessMessage(JMessage msg)
}
}
}
/* TODO */
/* { */
/* JWidget manager = get_manager(); */
/* View* view = View::getView(manager); */
/* if (view) { */
/* jview_update(view); */
/* } */
/* } */
break;
case JM_SETCURSOR:
if (m_is_moveable) {
int action = this->get_action(msg->mouse.x, msg->mouse.y);
HitTest ht = hitTest(gfx::Point(msg->mouse.x, msg->mouse.y));
int cursor = JI_CURSOR_NORMAL;
if (action == WINDOW_MOVE)
cursor = MOTION_CURSOR;
else if (action & WINDOW_RESIZE_LEFT) {
if (action & WINDOW_RESIZE_TOP)
switch (ht) {
case HitTestCaption:
cursor = JI_CURSOR_NORMAL;
break;
case HitTestBorderNW:
cursor = JI_CURSOR_SIZE_TL;
else if (action & WINDOW_RESIZE_BOTTOM)
cursor = JI_CURSOR_SIZE_BL;
else
break;
case HitTestBorderW:
cursor = JI_CURSOR_SIZE_L;
}
else if (action & WINDOW_RESIZE_RIGHT) {
if (action & WINDOW_RESIZE_TOP)
break;
case HitTestBorderSW:
cursor = JI_CURSOR_SIZE_BL;
break;
case HitTestBorderNE:
cursor = JI_CURSOR_SIZE_TR;
else if (action & WINDOW_RESIZE_BOTTOM)
cursor = JI_CURSOR_SIZE_BR;
else
break;
case HitTestBorderE:
cursor = JI_CURSOR_SIZE_R;
break;
case HitTestBorderSE:
cursor = JI_CURSOR_SIZE_BR;
break;
case HitTestBorderN:
cursor = JI_CURSOR_SIZE_T;
break;
case HitTestBorderS:
cursor = JI_CURSOR_SIZE_B;
break;
}
else if (action & WINDOW_RESIZE_TOP)
cursor = JI_CURSOR_SIZE_T;
else if (action & WINDOW_RESIZE_BOTTOM)
cursor = JI_CURSOR_SIZE_B;
jmouse_set_cursor(cursor);
return true;
@ -436,79 +516,6 @@ void Frame::window_set_position(JRect rect)
jrect_free(cpos);
}
int Frame::get_action(int x, int y)
{
int action = WINDOW_NONE;
JRect pos;
JRect cpos;
if (!m_is_moveable)
return action;
pos = jwidget_get_rect(this);
cpos = jwidget_get_child_rect(this);
/* move */
if ((this->hasText())
&& (((x >= cpos->x1) &&
(x < cpos->x2) &&
(y >= pos->y1+this->border_width.b) &&
(y < cpos->y1))
|| (key[KEY_ALT]))) {
action = WINDOW_MOVE;
}
/* resize */
else if (m_is_sizeable) {
/* left *****************************************/
if ((x >= pos->x1) && (x < cpos->x1)) {
action |= WINDOW_RESIZE_LEFT;
/* top */
if ((y >= pos->y1) && (y < cpos->y1)) {
action |= WINDOW_RESIZE_TOP;
}
/* bottom */
else if ((y > cpos->y2-1) && (y <= pos->y2-1))
action |= WINDOW_RESIZE_BOTTOM;
}
/* top *****************************************/
else if ((y >= pos->y1) && (y < cpos->y1)) {
action |= WINDOW_RESIZE_TOP;
/* left */
if ((x >= pos->x1) && (x < cpos->x1))
action |= WINDOW_RESIZE_LEFT;
/* right */
else if ((x > cpos->x2-1) && (x <= pos->x2-1))
action |= WINDOW_RESIZE_RIGHT;
}
/* right *****************************************/
else if ((x > cpos->x2-1) && (x <= pos->x2-1)) {
action |= WINDOW_RESIZE_RIGHT;
/* top */
if ((y >= pos->y1) && (y < cpos->y1)) {
action |= WINDOW_RESIZE_TOP;
}
/* bottom */
else if ((y > cpos->y2-1) && (y <= pos->y2-1))
action |= WINDOW_RESIZE_BOTTOM;
}
/* bottom *****************************************/
else if ((y > cpos->y2-1) && (y <= pos->y2-1)) {
action |= WINDOW_RESIZE_BOTTOM;
/* left */
if ((x >= pos->x1) && (x < cpos->x1))
action |= WINDOW_RESIZE_LEFT;
/* right */
else if ((x > cpos->x2-1) && (x <= pos->x2-1))
action |= WINDOW_RESIZE_RIGHT;
}
}
jrect_free(pos);
jrect_free(cpos);
return action;
}
void Frame::limit_size(int *w, int *h)
{
*w = MAX(*w, this->border_width.l+this->border_width.r);

View File

@ -9,21 +9,15 @@
#include "base/compiler_specific.h"
#include "base/signal.h"
#include "gfx/point.h"
#include "gui/event.h"
#include "gui/hit_test_event.h"
#include "gui/widget.h"
class CloseEvent { }; // TODO
class Frame : public Widget
{
JWidget m_killer;
bool m_is_desktop : 1;
bool m_is_moveable : 1;
bool m_is_sizeable : 1;
bool m_is_ontop : 1;
bool m_is_wantfocus : 1;
bool m_is_foreground : 1;
bool m_is_autoremap : 1;
public:
Frame(bool is_desktop, const char* text);
~Frame();
@ -47,18 +41,22 @@ public:
void closeWindow(Widget* killer);
bool is_toplevel();
bool is_foreground() const;
bool is_desktop() const;
bool is_ontop() const;
bool is_wantfocus() const;
bool is_foreground() const { return m_is_foreground; }
bool is_desktop() const { return m_is_desktop; }
bool is_ontop() const { return m_is_ontop; }
bool is_wantfocus() const { return m_is_wantfocus; }
bool is_moveable() const { return m_is_moveable; }
HitTest hitTest(const gfx::Point& point);
// Signals
Signal1<void, CloseEvent&> Close;
protected:
bool onProcessMessage(JMessage msg) OVERRIDE;
void onPreferredSize(PreferredSizeEvent& ev) OVERRIDE;
void onPaint(PaintEvent& ev) OVERRIDE;
virtual bool onProcessMessage(JMessage msg) OVERRIDE;
virtual void onPreferredSize(PreferredSizeEvent& ev) OVERRIDE;
virtual void onPaint(PaintEvent& ev) OVERRIDE;
virtual void onHitTest(HitTestEvent& ev);
private:
void window_set_position(JRect rect);
@ -66,7 +64,15 @@ private:
void limit_size(int* w, int* h);
void move_window(JRect rect, bool use_blit);
int m_windowAction;
JWidget m_killer;
bool m_is_desktop : 1;
bool m_is_moveable : 1;
bool m_is_sizeable : 1;
bool m_is_ontop : 1;
bool m_is_wantfocus : 1;
bool m_is_foreground : 1;
bool m_is_autoremap : 1;
int m_hitTest;
};
#endif

View File

@ -23,6 +23,7 @@
#include "gui/frame.h"
#include "gui/graphics.h"
#include "gui/grid.h"
#include "gui/hit_test_event.h"
#include "gui/hook.h"
#include "gui/image_view.h"
#include "gui/label.h"

45
src/gui/hit_test_event.h Normal file
View File

@ -0,0 +1,45 @@
// ASE gui library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef GUI_HIT_TEST_EVENT_H_INCLUDED
#define GUI_HIT_TEST_EVENT_H_INCLUDED
#include "gui/event.h"
enum HitTest
{
HitTestNowhere,
HitTestCaption,
HitTestClient,
HitTestBorderNW,
HitTestBorderN,
HitTestBorderNE,
HitTestBorderE,
HitTestBorderSE,
HitTestBorderS,
HitTestBorderSW,
HitTestBorderW,
};
class HitTestEvent : public Event
{
public:
HitTestEvent(Component* source, const gfx::Point& point, HitTest hit)
: Event(source)
, m_point(point)
, m_hit(hit) { }
gfx::Point getPoint() const { return m_point; }
HitTest getHit() const { return m_hit; }
void setHit(HitTest hit) { m_hit = hit; }
private:
gfx::Point m_point;
HitTest m_hit;
};
#endif // GUI_HIT_TEST_EVENT_H_INCLUDED

View File

@ -402,18 +402,24 @@ bool jmanager_generate_messages(JWidget manager)
}
}
/* Z-Order:
Send the window to top (only when you click in a window
that aren't the desktop) */
// Handle Z order: Send the window to top (only when you click in
// a window that aren't the desktop).
if (msg->type == JM_BUTTONPRESSED &&
!capture_widget && mouse_widget) {
// The clicked window
Frame* window = static_cast<Frame*>(mouse_widget->getRoot());
JWidget win_manager = window ? window->getManager(): NULL;
if ((window) &&
// We cannot change Z-order of desktop windows
(!window->is_desktop()) &&
// We cannot change Z order of foreground windows because a
// foreground window can launch other background windows
// which should be kept on top of the foreground one.
(!window->is_foreground()) &&
// If the window is not already the top window of the manager.
(window != TOPWND(win_manager))) {
/* put it in the top of the list */
// Put it in the top of the list
jlist_remove(win_manager->children, window);
if (window->is_ontop())
@ -432,7 +438,7 @@ bool jmanager_generate_messages(JWidget manager)
window->invalidate();
}
/* put the focus */
// Put the focus
jmanager_set_focus(mouse_widget);
}

View File

@ -40,15 +40,10 @@ PopupFrame::PopupFrame(const char* text, bool close_on_buttonpressed)
PopupFrame::~PopupFrame()
{
if (m_filtering) {
m_filtering = false;
jmanager_remove_msg_filter(JM_MOTION, this);
jmanager_remove_msg_filter(JM_BUTTONPRESSED, this);
jmanager_remove_msg_filter(JM_KEYPRESSED, this);
}
if (m_hot_region != NULL) {
stopFilteringMessages();
if (m_hot_region != NULL)
jregion_free(m_hot_region);
}
}
/**
@ -62,26 +57,29 @@ void PopupFrame::setHotRegion(JRegion region)
if (m_hot_region != NULL)
jregion_free(m_hot_region);
if (!m_filtering) {
m_filtering = true;
jmanager_add_msg_filter(JM_MOTION, this);
jmanager_add_msg_filter(JM_BUTTONPRESSED, this);
jmanager_add_msg_filter(JM_KEYPRESSED, this);
}
startFilteringMessages();
m_hot_region = region;
}
void PopupFrame::makeFloating()
{
stopFilteringMessages();
set_moveable(true);
}
void PopupFrame::makeFixed()
{
startFilteringMessages();
set_moveable(false);
}
bool PopupFrame::onProcessMessage(JMessage msg)
{
switch (msg->type) {
case JM_CLOSE:
if (m_filtering) {
m_filtering = false;
jmanager_remove_msg_filter(JM_MOTION, this);
jmanager_remove_msg_filter(JM_BUTTONPRESSED, this);
jmanager_remove_msg_filter(JM_KEYPRESSED, this);
}
stopFilteringMessages();
break;
case JM_SIGNAL:
@ -95,7 +93,7 @@ bool PopupFrame::onProcessMessage(JMessage msg)
break;
case JM_MOUSELEAVE:
if (m_hot_region == NULL)
if (m_hot_region == NULL && !is_moveable())
closeWindow(NULL);
break;
@ -109,31 +107,30 @@ bool PopupFrame::onProcessMessage(JMessage msg)
return false;
case JM_BUTTONPRESSED:
/* if the user click outside the window, we have to close the
tooltip window */
// If the user click outside the window, we have to close the
// tooltip window.
if (m_filtering) {
Widget* picked = this->pick(msg->mouse.x, msg->mouse.y);
if (!picked || picked->getRoot() != this) {
this->closeWindow(NULL);
closeWindow(NULL);
}
}
/* this is used when the user click inside a small text
tooltip */
// This is used when the user click inside a small text tooltip.
if (m_close_on_buttonpressed)
this->closeWindow(NULL);
closeWindow(NULL);
break;
case JM_MOTION:
if (m_hot_region != NULL &&
if (!is_moveable() &&
m_hot_region != NULL &&
jmanager_get_capture() == NULL) {
struct jrect box;
/* if the mouse is outside the hot-region we have to close the window */
if (!jregion_point_in(m_hot_region,
msg->mouse.x, msg->mouse.y, &box)) {
this->closeWindow(NULL);
}
// If the mouse is outside the hot-region we have to close the
// window.
if (!jregion_point_in(m_hot_region, msg->mouse.x, msg->mouse.y, &box))
closeWindow(NULL);
}
break;
@ -191,3 +188,23 @@ void PopupFrame::onPaint(PaintEvent& ev)
g->drawString(getText(), ji_color_foreground(), this->getBgColor(), pos, getAlign());
}
void PopupFrame::startFilteringMessages()
{
if (!m_filtering) {
m_filtering = true;
jmanager_add_msg_filter(JM_MOTION, this);
jmanager_add_msg_filter(JM_BUTTONPRESSED, this);
jmanager_add_msg_filter(JM_KEYPRESSED, this);
}
}
void PopupFrame::stopFilteringMessages()
{
if (m_filtering) {
m_filtering = false;
jmanager_remove_msg_filter(JM_MOTION, this);
jmanager_remove_msg_filter(JM_BUTTONPRESSED, this);
jmanager_remove_msg_filter(JM_KEYPRESSED, this);
}
}

View File

@ -18,12 +18,18 @@ public:
void setHotRegion(JRegion region);
void makeFloating();
void makeFixed();
protected:
bool onProcessMessage(JMessage msg) OVERRIDE;
void onPreferredSize(PreferredSizeEvent& ev) OVERRIDE;
void onPaint(PaintEvent& ev) OVERRIDE;
private:
void startFilteringMessages();
void stopFilteringMessages();
bool m_close_on_buttonpressed;
JRegion m_hot_region;
bool m_filtering;

View File

@ -810,6 +810,11 @@ void get_widgets(JWidget window, ...)
}
void setup_mini_look(Widget* widget)
{
setup_look(widget, MiniLook);
}
void setup_look(Widget* widget, LookType lookType)
{
SharedPtr<SkinProperty> skinProp;
@ -817,7 +822,7 @@ void setup_mini_look(Widget* widget)
if (skinProp == NULL)
skinProp.reset(new SkinProperty);
skinProp->setMiniLook(true);
skinProp->setLook(lookType);
widget->setProperty(skinProp);
}

View File

@ -24,6 +24,7 @@
#include "base/exception.h"
#include "gui/base.h"
#include "gui/accel.h"
#include "skin/skin_property.h"
class ButtonBase;
class CheckBox;
@ -93,6 +94,7 @@ void hook_signal(Widget* widget,
void get_widgets(Widget* window, ...);
void setup_mini_look(Widget* widget);
void setup_look(Widget* widget, LookType lookType);
void setup_bevels(Widget* widget, int b1, int b2, int b3, int b4);
void set_gfxicon_to_button(ButtonBase* button,

View File

@ -465,6 +465,9 @@ enum {
PART_LAYER_LOCKED,
PART_LAYER_LOCKED_SELECTED,
PART_UNPINNED,
PART_PINNED,
PARTS
};

View File

@ -25,7 +25,7 @@ const char* SkinProperty::SkinPropertyName = "SkinProperty";
SkinProperty::SkinProperty()
: Property(SkinPropertyName)
{
m_isMiniLook = false;
m_look = NormalLook;
m_upperLeft = 0;
m_upperRight = 0;
m_lowerLeft = 0;
@ -35,53 +35,3 @@ SkinProperty::SkinProperty()
SkinProperty::~SkinProperty()
{
}
bool SkinProperty::isMiniLook() const
{
return m_isMiniLook;
}
void SkinProperty::setMiniLook(bool state)
{
m_isMiniLook = state;
}
int SkinProperty::getUpperLeft() const
{
return m_upperLeft;
}
int SkinProperty::getUpperRight() const
{
return m_upperRight;
}
int SkinProperty::getLowerLeft() const
{
return m_lowerLeft;
}
int SkinProperty::getLowerRight() const
{
return m_lowerRight;
}
void SkinProperty::setUpperLeft(int value)
{
m_upperLeft = value;
}
void SkinProperty::setUpperRight(int value)
{
m_upperRight = value;
}
void SkinProperty::setLowerLeft(int value)
{
m_lowerLeft = value;
}
void SkinProperty::setLowerRight(int value)
{
m_lowerRight = value;
}

View File

@ -21,6 +21,12 @@
#include "gui/property.h"
enum LookType {
NormalLook,
MiniLook,
WithoutBordersLook,
};
// Property to show widgets with a special look (e.g.: buttons or sliders with mini-borders)
class SkinProperty : public Property
{
@ -30,21 +36,21 @@ public:
SkinProperty();
~SkinProperty();
bool isMiniLook() const;
void setMiniLook(bool state);
LookType getLook() const { return m_look; }
void setLook(LookType look) { m_look = look; }
int getUpperLeft() const;
int getUpperRight() const;
int getLowerLeft() const;
int getLowerRight() const;
int getUpperLeft() const { return m_upperLeft; }
int getUpperRight() const { return m_upperRight; }
int getLowerLeft() const { return m_lowerLeft; }
int getLowerRight() const { return m_lowerRight; }
void setUpperLeft(int value);
void setUpperRight(int value);
void setLowerLeft(int value);
void setLowerRight(int value);
void setUpperLeft(int value) { m_upperLeft = value; }
void setUpperRight(int value) { m_upperRight = value; }
void setLowerLeft(int value) { m_lowerLeft = value; }
void setLowerRight(int value) { m_lowerRight = value; }
private:
bool m_isMiniLook;
LookType m_look;
int m_upperLeft;
int m_upperRight;
int m_lowerLeft;

View File

@ -198,6 +198,8 @@ SkinTheme::SkinTheme()
sheet_mapping["layer_editable_selected"] = PART_LAYER_EDITABLE_SELECTED;
sheet_mapping["layer_locked"] = PART_LAYER_LOCKED;
sheet_mapping["layer_locked_selected"] = PART_LAYER_LOCKED_SELECTED;
sheet_mapping["unpinned"] = PART_UNPINNED;
sheet_mapping["pinned"] = PART_PINNED;
reload_skin();
}
@ -719,24 +721,24 @@ void SkinTheme::paintButton(PaintEvent& ev)
iconInterface ? iconInterface->getHeight() : 0);
// Tool buttons are smaller
bool isMiniLook = false;
LookType look = NormalLook;
SharedPtr<SkinProperty> skinPropery = widget->getProperty(SkinProperty::SkinPropertyName);
if (skinPropery != NULL)
isMiniLook = skinPropery->isMiniLook();
look = skinPropery->getLook();
// selected
if (widget->isSelected()) {
fg = get_button_selected_text_color();
bg = get_button_selected_face_color();
part_nw = isMiniLook ? PART_TOOLBUTTON_NORMAL_NW:
PART_BUTTON_SELECTED_NW;
part_nw = (look == MiniLook ? PART_TOOLBUTTON_NORMAL_NW:
PART_BUTTON_SELECTED_NW);
}
// with mouse
else if (widget->isEnabled() && widget->hasMouseOver()) {
fg = get_button_hot_text_color();
bg = get_button_hot_face_color();
part_nw = isMiniLook ? PART_TOOLBUTTON_HOT_NW:
PART_BUTTON_HOT_NW;
part_nw = (look == MiniLook ? PART_TOOLBUTTON_HOT_NW:
PART_BUTTON_HOT_NW);
}
// without mouse
else {
@ -744,11 +746,11 @@ void SkinTheme::paintButton(PaintEvent& ev)
bg = get_button_normal_face_color();
if (widget->hasFocus())
part_nw = isMiniLook ? PART_TOOLBUTTON_HOT_NW:
PART_BUTTON_FOCUSED_NW;
part_nw = (look == MiniLook ? PART_TOOLBUTTON_HOT_NW:
PART_BUTTON_FOCUSED_NW);
else
part_nw = isMiniLook ? PART_TOOLBUTTON_NORMAL_NW:
PART_BUTTON_NORMAL_NW;
part_nw = (look == MiniLook ? PART_TOOLBUTTON_NORMAL_NW:
PART_BUTTON_NORMAL_NW);
}
// widget position
@ -791,10 +793,16 @@ void SkinTheme::paintCheckBox(PaintEvent& ev)
iconInterface ? iconInterface->getWidth() : 0,
iconInterface ? iconInterface->getHeight() : 0);
// background
// Check box look
LookType look = NormalLook;
SharedPtr<SkinProperty> skinPropery = widget->getProperty(SkinProperty::SkinPropertyName);
if (skinPropery != NULL)
look = skinPropery->getLook();
// Background
jdraw_rectfill(widget->rc, bg = BGCOLOR);
// mouse
// Mouse
if (widget->isEnabled()) {
if (widget->hasMouseOver())
jdraw_rectfill(widget->rc, bg = get_check_hot_face_color());
@ -802,7 +810,7 @@ void SkinTheme::paintCheckBox(PaintEvent& ev)
jdraw_rectfill(widget->rc, bg = get_check_focus_face_color());
}
/* text */
// Text
draw_textstring(NULL, -1, bg, false, widget, &text, 0);
// Paint the icon
@ -810,7 +818,7 @@ void SkinTheme::paintCheckBox(PaintEvent& ev)
paintIcon(widget, ev.getGraphics(), iconInterface, icon.x1-widget->rc->x1, icon.y1-widget->rc->y1);
// draw focus
if (widget->hasFocus()) {
if (look != WithoutBordersLook && widget->hasFocus()) {
draw_bounds_nw(ji_screen,
widget->rc->x1,
widget->rc->y1,
@ -1222,7 +1230,7 @@ void SkinTheme::paintSlider(PaintEvent& ev)
SharedPtr<SkinProperty> skinPropery = widget->getProperty(SkinProperty::SkinPropertyName);
if (skinPropery != NULL)
isMiniLook = skinPropery->isMiniLook();
isMiniLook = (skinPropery->getLook() == MiniLook);
if (SkinSliderProperty* sliderProperty = dynamic_cast<SkinSliderProperty*>(skinPropery.get()))
bgPainter = sliderProperty->getBgPainter();

View File

@ -86,6 +86,11 @@ bool ColorButton::onProcessMessage(JMessage msg)
{
switch (msg->type) {
case JM_CLOSE:
if (m_frame && m_frame->isVisible())
m_frame->closeWindow(NULL);
break;
case JM_MOUSEENTER:
app_get_statusbar()->showColor(0, "", m_color, 255);
break;
@ -101,7 +106,7 @@ bool ColorButton::onProcessMessage(JMessage msg)
// Open it
openSelectorDialog();
}
else {
else if (!m_frame->is_moveable()) {
// If it is visible, close it
closeSelectorDialog();
}

View File

@ -36,7 +36,7 @@
#include "widgets/palette_view.h"
ColorSelector::ColorSelector()
: PopupFrame("Color Selector", false)
: PopupFramePin("Color Selector", false)
, m_color(Color::fromMask())
, m_vbox(JI_VERTICAL)
, m_topBox(JI_HORIZONTAL)
@ -70,6 +70,14 @@ ColorSelector::ColorSelector()
jwidget_add_child(&m_topBox, &m_grayButton);
jwidget_add_child(&m_topBox, &m_maskButton);
jwidget_add_child(&m_topBox, &m_hexColorEntry);
{
Box* filler = new Box(JI_HORIZONTAL);
Box* miniVbox = new Box(JI_VERTICAL);
jwidget_expansive(filler, true);
jwidget_add_child(&m_topBox, filler);
jwidget_add_child(&m_topBox, miniVbox);
jwidget_add_child(miniVbox, getPin());
}
jwidget_add_child(&m_vbox, &m_topBox);
jwidget_add_child(&m_vbox, &m_colorPaletteContainer);
jwidget_add_child(&m_vbox, &m_rgbSliders);
@ -96,6 +104,11 @@ ColorSelector::ColorSelector()
initTheme();
}
ColorSelector::~ColorSelector()
{
jwidget_remove_child(getPin()->getParent(), getPin());
}
void ColorSelector::setColor(const Color& color)
{
m_color = color;

View File

@ -24,16 +24,17 @@
#include "gui/button.h"
#include "gui/grid.h"
#include "gui/label.h"
#include "gui/popup_frame.h"
#include "gui/view.h"
#include "widgets/color_sliders.h"
#include "widgets/popup_frame_pin.h"
#include "widgets/hex_color_entry.h"
#include "widgets/palette_view.h"
class ColorSelector : public PopupFrame
class ColorSelector : public PopupFramePin
{
public:
ColorSelector();
~ColorSelector();
void setColor(const Color& color);
Color getColor() const;

View File

@ -0,0 +1,87 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2011 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "widgets/popup_frame_pin.h"
#include "base/bind.h"
#include "gfx/border.h"
#include "gfx/size.h"
#include "gui/gui.h"
#include "modules/gfx.h"
#include "modules/gui.h"
#include "skin/skin_theme.h"
#include <allegro.h>
#include <vector>
PopupFramePin::PopupFramePin(const char* text, bool close_on_buttonpressed)
: PopupFrame(text, close_on_buttonpressed)
, m_pin("")
{
// Configure the micro check-box look without borders, only the "pin" icon is shown.
setup_look(&m_pin, WithoutBordersLook);
m_pin.child_spacing = 0;
m_pin.setBorder(gfx::Border(0));
m_pin.Click.connect(&PopupFramePin::onPinClick, this);
set_gfxicon_to_button(&m_pin, PART_UNPINNED, PART_PINNED, PART_UNPINNED, JI_CENTER | JI_MIDDLE);
}
void PopupFramePin::onPinClick(Event& ev)
{
if (m_pin.isSelected()) {
makeFloating();
}
else {
JRect rc = jrect_new(this->rc->x1-8, this->rc->y1-8, this->rc->x2+8, this->rc->y2+8);
JRegion rgn = jregion_new(rc, 1);
jrect_free(rc);
setHotRegion(rgn);
makeFixed();
}
}
bool PopupFramePin::onProcessMessage(JMessage msg)
{
switch (msg->type) {
case JM_OPEN:
m_pin.setSelected(false);
makeFixed();
break;
case JM_CLOSE:
m_pin.setSelected(false);
break;
}
return PopupFrame::onProcessMessage(msg);
}
void PopupFramePin::onHitTest(HitTestEvent& ev)
{
PopupFrame::onHitTest(ev);
if (m_pin.isSelected() && ev.getHit() == HitTestClient)
ev.setHit(HitTestCaption);
}

View File

@ -0,0 +1,45 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2011 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WIDGETS_POPUP_FRAME_PIN_H_INCLUDED
#define WIDGETS_POPUP_FRAME_PIN_H_INCLUDED
#include "gui/button.h"
#include "gui/popup_frame.h"
class PopupFramePin : public PopupFrame
{
public:
PopupFramePin(const char* text, bool close_on_buttonpressed);
protected:
virtual bool onProcessMessage(JMessage msg) OVERRIDE;
virtual void onHitTest(HitTestEvent& ev) 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
// parent in your class's dtor.
CheckBox* getPin() { return &m_pin; }
private:
void onPinClick(Event& ev);
CheckBox m_pin;
};
#endif