Add PreferredSizeEvent and Widget::onPreferredSize to replace JM_REQSIZE message.

There are a lot of widgets in C code, so JM_REQSIZE cannot be removed until all widgets are converted to C++ classes.
This commit is contained in:
David Capello 2010-08-02 22:57:41 -03:00
parent ec7795fc33
commit 01c811e726
23 changed files with 634 additions and 238 deletions

View File

@ -510,9 +510,11 @@ VACA_SOURCES = \
$(VACA_DIR)/src/Application.cpp \
$(VACA_DIR)/src/Component.cpp \
$(VACA_DIR)/src/Debug.cpp \
$(VACA_DIR)/src/Event.cpp \
$(VACA_DIR)/src/Exception.cpp \
$(VACA_DIR)/src/Mutex.cpp \
$(VACA_DIR)/src/Point.cpp \
$(VACA_DIR)/src/PreferredSizeEvent.cpp \
$(VACA_DIR)/src/Property.cpp \
$(VACA_DIR)/src/Rect.cpp \
$(VACA_DIR)/src/Referenceable.cpp \

View File

@ -25,6 +25,7 @@
#include <vector>
#include "Vaca/Bind.h"
#include "Vaca/Size.h"
#include "jinete/jinete.h"
#include "app.h"
@ -50,6 +51,8 @@
#include "sprite_wrappers.h"
#include "ui_context.h"
using Vaca::Size;
static Frame* window = NULL;
static int redraw_timer_id = -1;
static bool redraw_all = false;
@ -997,20 +1000,20 @@ static bool select_hsv_hook(JWidget widget, void *data)
static bool expand_button_select_hook(JWidget widget, void *data)
{
int req_w, req_h;
Size reqSize;
if (more_options->isVisible()) {
set_config_bool("PaletteEditor", "ShowMoreOptions", false);
more_options->setVisible(false);
// Get the required size of the "More options" panel
jwidget_request_size(more_options, &req_w, &req_h);
req_h += 4;
reqSize = more_options->getPreferredSize();
reqSize.h += 4;
// Remove the space occupied by the "More options" panel
{
JRect rect = jrect_new(window->rc->x1, window->rc->y1,
window->rc->x2, window->rc->y2 - req_h);
window->rc->x2, window->rc->y2 - reqSize.h);
window->move_window(rect);
jrect_free(rect);
}
@ -1020,12 +1023,12 @@ static bool expand_button_select_hook(JWidget widget, void *data)
more_options->setVisible(true);
// Get the required size of the whole window
jwidget_request_size(window, &req_w, &req_h);
reqSize = window->getPreferredSize();
// Add space for the "more_options" panel
if (jrect_h(window->rc) < req_h) {
if (jrect_h(window->rc) < reqSize.h) {
JRect rect = jrect_new(window->rc->x1, window->rc->y1,
window->rc->x2, window->rc->y1 + req_h);
window->rc->x2, window->rc->y1 + reqSize.h);
// Show the expanded area inside the screen
if (rect->y2 > JI_SCREEN_H)

View File

@ -38,6 +38,7 @@
#include "jinete/jrect.h"
#include "jinete/jwidget.h"
#include "jinete/jtheme.h"
#include "Vaca/Size.h"
static bool box_msg_proc(JWidget widget, JMessage msg);
static void box_request_size(JWidget widget, int *w, int *h);
@ -80,11 +81,11 @@ static void box_request_size(JWidget widget, int *w, int *h)
#define GET_CHILD_SIZE(w, h) \
{ \
if (widget->getAlign() & JI_HOMOGENEOUS) \
*w = MAX(*w, req_##w); \
*w = MAX(*w, reqSize.w); \
else \
*w += req_##w; \
*w += reqSize.w; \
\
*h = MAX(*h, req_##h); \
*h = MAX(*h, reqSize.h); \
}
#define FINAL_SIZE(w) \
@ -96,7 +97,6 @@ static void box_request_size(JWidget widget, int *w, int *h)
}
int nvis_children;
int req_w, req_h;
JWidget child;
JLink link;
@ -115,7 +115,7 @@ static void box_request_size(JWidget widget, int *w, int *h)
if (child->flags & JI_HIDDEN)
continue;
jwidget_request_size(child, &req_w, &req_h);
Size reqSize = child->getPreferredSize();
if (widget->getAlign() & JI_HORIZONTAL) {
GET_CHILD_SIZE(w, h);
@ -151,7 +151,7 @@ static void box_set_position(JWidget widget, JRect rect)
extra = width / nvis_children; \
} \
else if (nexpand_children > 0) { \
width = jrect_##w(widget->rc) - req_##w; \
width = jrect_##w(widget->rc) - reqSize.w; \
extra = width / nexpand_children; \
} \
else { \
@ -179,9 +179,9 @@ static void box_set_position(JWidget widget, JRect rect)
width -= extra; \
} \
else { \
jwidget_request_size(child, &req_w, &req_h); \
reqSize = child->getPreferredSize(); \
\
child_width = req_##w; \
child_width = reqSize.w; \
\
if (jwidget_is_expansive(child)) { \
if (nexpand_children == 1) \
@ -213,7 +213,6 @@ static void box_set_position(JWidget widget, JRect rect)
JWidget child;
int nvis_children = 0;
int nexpand_children = 0;
int req_w, req_h;
int child_width;
JLink link;
int width;
@ -232,7 +231,7 @@ static void box_set_position(JWidget widget, JRect rect)
}
}
jwidget_request_size(widget, &req_w, &req_h);
Size reqSize = widget->getPreferredSize();
if (widget->getAlign() & JI_HORIZONTAL) {
FIXUP(x, y, w, h, l, t, r, b);

View File

@ -34,6 +34,8 @@
#include <allegro.h>
#include "jinete/jinete.h"
#include "Vaca/Size.h"
#include "Vaca/PreferredSizeEvent.h"
struct ComboBox::Item
{
@ -267,47 +269,16 @@ bool ComboBox::onProcessMessage(JMessage msg)
closeListBox();
break;
case JM_REQSIZE: {
int w, h;
msg->reqsize.w = 0;
msg->reqsize.h = 0;
jwidget_request_size(m_entry, &w, &h);
// Get the text-length of every item and put in 'w' the maximum value
std::vector<Item*>::iterator it, end = m_items.end();
for (it = m_items.begin(); it != end; ++it) {
int item_w =
2*jguiscale()+
text_length(this->getFont(), (*it)->text.c_str())+
10*jguiscale();
w = MAX(w, item_w);
}
msg->reqsize.w += w;
msg->reqsize.h += h;
jwidget_request_size(m_button, &w, &h);
msg->reqsize.w += w;
msg->reqsize.h = MAX(msg->reqsize.h, h);
return true;
}
case JM_SETPOS: {
JRect cbox = jrect_new_copy(&msg->setpos.rect);
int w, h;
jrect_copy(this->rc, cbox);
/* button */
jwidget_request_size(m_button, &w, &h);
cbox->x1 = msg->setpos.rect.x2 - w;
// Button
Size buttonSize = m_button->getPreferredSize();
cbox->x1 = msg->setpos.rect.x2 - buttonSize.w;
jwidget_set_rect(m_button, cbox);
/* entry */
// Entry
cbox->x2 = cbox->x1;
cbox->x1 = msg->setpos.rect.x1;
jwidget_set_rect(m_entry, cbox);
@ -338,6 +309,31 @@ bool ComboBox::onProcessMessage(JMessage msg)
return Widget::onProcessMessage(msg);
}
void ComboBox::onPreferredSize(PreferredSizeEvent& ev)
{
Size reqSize(0, 0);
Size entrySize = m_entry->getPreferredSize();
// Get the text-length of every item and put in 'w' the maximum value
std::vector<Item*>::iterator it, end = m_items.end();
for (it = m_items.begin(); it != end; ++it) {
int item_w =
2*jguiscale()+
text_length(this->getFont(), (*it)->text.c_str())+
10*jguiscale();
reqSize.w = MAX(reqSize.w, item_w);
}
reqSize.w += entrySize.w;
reqSize.h += entrySize.h;
Size buttonSize = m_button->getPreferredSize();
reqSize.w += buttonSize.w;
reqSize.h = MAX(reqSize.h, buttonSize.h);
ev.setPreferredSize(reqSize);
}
static bool combobox_entry_msg_proc(JWidget widget, JMessage msg)
{
ComboBox* combobox = reinterpret_cast<ComboBox*>(widget->user_data[0]);

View File

@ -79,6 +79,7 @@ public:
protected:
bool onProcessMessage(JMessage msg);
void onPreferredSize(PreferredSizeEvent& ev);
private:
struct Item;

View File

@ -41,6 +41,7 @@
#include "jinete/jrect.h"
#include "jinete/jwidget.h"
#include "jinete/jtheme.h"
#include "Vaca/Size.h"
struct Cell
{
@ -214,7 +215,7 @@ static void grid_set_position(JWidget widget, JRect rect)
Grid* grid = reinterpret_cast<Grid*>(jwidget_get_data(widget, JI_GRID));
JRect cpos = jrect_new(0, 0, 0, 0);
int pos_x, pos_y;
int req_w, req_h;
Size reqSize;
int x, y, w, h;
int col, row;
int i, j;
@ -251,30 +252,30 @@ static void grid_set_position(JWidget widget, JRect rect)
CALCULATE_CELL_SIZE(col, hspan, colstrip, w);
CALCULATE_CELL_SIZE(row, vspan, rowstrip, h);
jwidget_request_size(cell->child, &req_w, &req_h);
reqSize = cell->child->getPreferredSize();
if (cell->align & JI_LEFT) {
w = req_w;
w = reqSize.w;
}
else if (cell->align & JI_CENTER) {
x += w/2 - req_w/2;
w = req_w;
x += w/2 - reqSize.w/2;
w = reqSize.w;
}
else if (cell->align & JI_RIGHT) {
x += w - req_w;
w = req_w;
x += w - reqSize.w;
w = reqSize.w;
}
if (cell->align & JI_TOP) {
h = req_h;
h = reqSize.h;
}
else if (cell->align & JI_MIDDLE) {
y += h/2 - req_h/2;
h = req_h;
y += h/2 - reqSize.h/2;
h = reqSize.h;
}
else if (cell->align & JI_BOTTOM) {
y += h - req_h;
h = req_h;
y += h - reqSize.h;
h = reqSize.h;
}
jrect_replace(cpos, x, y, x+w, y+h);
@ -299,7 +300,7 @@ static void grid_calculate_size(JWidget widget)
{
Grid* grid = reinterpret_cast<Grid*>(jwidget_get_data(widget, JI_GRID));
int row, col, size;
int req_w, req_h;
Size reqSize;
int i, expand;
int expand_count;
int last_expand;
@ -320,15 +321,15 @@ static void grid_calculate_size(JWidget widget)
for (p_row=0; p_row<grid->p_rows; ++p_row) { \
/* for each cell */ \
cell = grid->cells[row]+col; \
req_w = req_h = 0; \
reqSize.w = reqSize.h = 0; \
\
if (cell->child != NULL) { \
if (cell->parent == NULL) { \
/* if the widget isn't hidden then we can request its size */ \
if (!(cell->child->flags & JI_HIDDEN)) { \
jwidget_request_size(cell->child, &req_w, &req_h); \
cell->w = req_w - (cell->hspan-1) * widget->child_spacing; \
cell->h = req_h - (cell->vspan-1) * widget->child_spacing; \
reqSize = cell->child->getPreferredSize(); \
cell->w = reqSize.w - (cell->hspan-1) * widget->child_spacing; \
cell->h = reqSize.h - (cell->vspan-1) * widget->child_spacing; \
if ((cell->align & p_align) == p_align) \
++expand_count; \
} \
@ -397,8 +398,8 @@ static void grid_calculate_size(JWidget widget)
++current_span; \
} while (more_span);
CALCULATE_STRIPS(col, cols, row, rows, vspan, req_w, colstrip, JI_HORIZONTAL);
CALCULATE_STRIPS(row, rows, col, cols, hspan, req_h, rowstrip, JI_VERTICAL);
CALCULATE_STRIPS(col, cols, row, rows, vspan, reqSize.w, colstrip, JI_HORIZONTAL);
CALCULATE_STRIPS(row, rows, col, cols, hspan, reqSize.h, rowstrip, JI_VERTICAL);
EXPAND_STRIPS(col, cols, row, rows, hspan, w, colstrip, grid_inc_col_size);
EXPAND_STRIPS(row, rows, col, cols, vspan, h, rowstrip, grid_inc_row_size);

View File

@ -41,6 +41,7 @@
#include "jinete/jtheme.h"
#include "jinete/jview.h"
#include "jinete/jwidget.h"
#include "Vaca/Size.h"
static bool listbox_msg_proc(JWidget widget, JMessage msg);
static void listbox_request_size(JWidget widget, int *w, int *h);
@ -326,16 +327,16 @@ static bool listbox_msg_proc(JWidget widget, JMessage msg)
static void listbox_request_size(JWidget widget, int *w, int *h)
{
int req_w, req_h;
Size reqSize;
JLink link;
*w = *h = 0;
JI_LIST_FOR_EACH(widget->children, link) {
jwidget_request_size(reinterpret_cast<JWidget>(link->data), &req_w, &req_h);
reqSize = reinterpret_cast<Widget*>(link->data)->getPreferredSize();
*w = MAX(*w, req_w);
*h += req_h + ((link->next)? widget->child_spacing: 0);
*w = MAX(*w, reqSize.w);
*h += reqSize.h + ((link->next)? widget->child_spacing: 0);
}
*w += widget->border_width.l + widget->border_width.r;
@ -344,7 +345,7 @@ static void listbox_request_size(JWidget widget, int *w, int *h)
static void listbox_set_position(JWidget widget, JRect rect)
{
int req_w, req_h;
Size reqSize;
JWidget child;
JRect cpos;
JLink link;
@ -355,9 +356,9 @@ static void listbox_set_position(JWidget widget, JRect rect)
JI_LIST_FOR_EACH(widget->children, link) {
child = (JWidget)link->data;
jwidget_request_size(child, &req_w, &req_h);
reqSize = child->getPreferredSize();
cpos->y2 = cpos->y1+req_h;
cpos->y2 = cpos->y1+reqSize.h;
jwidget_set_rect(child, cpos);
cpos->y1 += jrect_h(child->rc) + widget->child_spacing;
@ -427,24 +428,24 @@ static bool listitem_msg_proc(JWidget widget, JMessage msg)
static void listitem_request_size(JWidget widget, int *w, int *h)
{
int max_w, max_h;
int req_w, req_h;
Size maxSize;
Size reqSize;
JLink link;
if (widget->hasText()) {
max_w = jwidget_get_text_length(widget);
max_h = jwidget_get_text_height(widget);
maxSize.w = jwidget_get_text_length(widget);
maxSize.h = jwidget_get_text_height(widget);
}
else
max_w = max_h = 0;
maxSize.w = maxSize.h = 0;
JI_LIST_FOR_EACH(widget->children, link) {
jwidget_request_size(reinterpret_cast<JWidget>(link->data), &req_w, &req_h);
reqSize = reinterpret_cast<Widget*>(link->data)->getPreferredSize();
max_w = MAX(max_w, req_w);
max_h = MAX(max_h, req_h);
maxSize.w = MAX(maxSize.w, reqSize.w);
maxSize.h = MAX(maxSize.h, reqSize.h);
}
*w = widget->border_width.l + max_w + widget->border_width.r;
*h = widget->border_width.t + max_h + widget->border_width.b;
*w = widget->border_width.l + maxSize.w + widget->border_width.r;
*h = widget->border_width.t + maxSize.h + widget->border_width.b;
}

View File

@ -38,6 +38,7 @@
#include "jinete/jinete.h"
#include "jinete/jintern.h"
#include "Vaca/Size.h"
/**********************************************************************/
/* Internal messages: to move between menus */
@ -405,23 +406,23 @@ static bool menu_msg_proc(JWidget widget, JMessage msg)
static void menu_request_size(JWidget widget, int *w, int *h)
{
int req_w, req_h;
Size reqSize;
JLink link;
*w = *h = 0;
JI_LIST_FOR_EACH(widget->children, link) {
jwidget_request_size((JWidget)link->data, &req_w, &req_h);
reqSize = ((Widget*)link->data)->getPreferredSize();
if (widget->parent->type == JI_MENUBAR) {
*w += req_w + ((link->next != widget->children->end) ?
widget->child_spacing: 0);
*h = MAX(*h, req_h);
*w += reqSize.w + ((link->next != widget->children->end) ?
widget->child_spacing: 0);
*h = MAX(*h, reqSize.h);
}
else {
*w = MAX(*w, req_w);
*h += req_h + ((link->next != widget->children->end) ?
widget->child_spacing: 0);
*w = MAX(*w, reqSize.w);
*h += reqSize.h + ((link->next != widget->children->end) ?
widget->child_spacing: 0);
}
}
@ -431,7 +432,7 @@ static void menu_request_size(JWidget widget, int *w, int *h)
static void menu_set_position(JWidget widget, JRect rect)
{
int req_w, req_h;
Size reqSize;
JWidget child;
JRect cpos;
JLink link;
@ -442,12 +443,12 @@ static void menu_set_position(JWidget widget, JRect rect)
JI_LIST_FOR_EACH(widget->children, link) {
child = (JWidget)link->data;
jwidget_request_size(child, &req_w, &req_h);
reqSize = child->getPreferredSize();
if (widget->parent->type == JI_MENUBAR)
cpos->x2 = cpos->x1+req_w;
cpos->x2 = cpos->x1+reqSize.w;
else
cpos->y2 = cpos->y1+req_h;
cpos->y2 = cpos->y1+reqSize.h;
jwidget_set_rect(child, cpos);
@ -780,8 +781,11 @@ static void menubox_request_size(JWidget widget, int *w, int *h)
{
JWidget menu = jmenubox_get_menu(widget);
if (menu)
jwidget_request_size(menu, w, h);
if (menu) {
Size reqSize = menu->getPreferredSize();
*w = reqSize.w;
*h = reqSize.h;
}
else
*w = *h = 0;

View File

@ -37,6 +37,7 @@
#include "jinete/jsystem.h"
#include "jinete/jtheme.h"
#include "jinete/jwidget.h"
#include "Vaca/Size.h"
typedef struct Panel
{
@ -227,8 +228,8 @@ static void panel_request_size(JWidget widget, int *w, int *h)
{
#define GET_CHILD_SIZE(w, h) \
do { \
*w = MAX(*w, req_##w); \
*h = MAX(*h, req_##h); \
*w = MAX(*w, reqSize.w); \
*h = MAX(*h, reqSize.h); \
} while(0)
#define FINAL_SIZE(w) \
@ -238,7 +239,7 @@ static void panel_request_size(JWidget widget, int *w, int *h)
} while(0)
int nvis_children;
int req_w, req_h;
Size reqSize;
JWidget child;
JLink link;
@ -257,7 +258,7 @@ static void panel_request_size(JWidget widget, int *w, int *h)
if (child->flags & JI_HIDDEN)
continue;
jwidget_request_size(child, &req_w, &req_h);
reqSize = child->getPreferredSize();
if (widget->getAlign() & JI_HORIZONTAL)
GET_CHILD_SIZE(w, h);
@ -286,7 +287,7 @@ static void panel_set_position(JWidget widget, JRect rect)
pos->y##1 = widget->rc->y##1; \
pos->x##2 = pos->x##1 + avail*panel->pos/100; \
/* TODO uncomment this to make a restricted panel */ \
/* pos->w = MID(req1_##w, pos->w, avail-req2_##w); */ \
/* pos->w = MID(reqSize1.w, pos->w, avail-reqSize2.w); */ \
pos->y##2 = pos->y##1 + jrect_##h(widget->rc); \
\
jwidget_set_rect(child1, pos); \
@ -309,11 +310,8 @@ static void panel_set_position(JWidget widget, JRect rect)
if (jlist_length(widget->children) == 2) {
JWidget child1 = reinterpret_cast<JWidget>(jlist_first(widget->children)->data);
JWidget child2 = reinterpret_cast<JWidget>(jlist_first(widget->children)->next->data);
int req1_w, req1_h;
int req2_w, req2_h;
jwidget_request_size(child1, &req1_w, &req1_h);
jwidget_request_size(child2, &req2_w, &req2_h);
//Size reqSize1 = child1->getPreferredSize();
//Size reqSize2 = child2->getPreferredSize();
if (widget->getAlign() & JI_HORIZONTAL)
FIXUP(x, y, w, h, l, t, r, b);

View File

@ -36,6 +36,8 @@
#include "jinete/jinete.h"
#include "jinete/jintern.h"
#include "Vaca/Size.h"
#include "Vaca/PreferredSizeEvent.h"
PopupWindow::PopupWindow(const char* text, bool close_on_buttonpressed)
: Frame(false, text)
@ -104,37 +106,6 @@ bool PopupWindow::onProcessMessage(JMessage msg)
}
break;
case JM_REQSIZE: {
int w = 0, h = 0;
_ji_theme_textbox_draw(NULL, this, &w, &h, 0, 0);
msg->reqsize.w = w;
msg->reqsize.h = this->border_width.t + this->border_width.b;
if (!jlist_empty(this->children)) {
int max_w, max_h;
int req_w, req_h;
JWidget child;
JLink link;
max_w = max_h = 0;
JI_LIST_FOR_EACH(this->children, link) {
child = (JWidget)link->data;
jwidget_request_size(child, &req_w, &req_h);
max_w = MAX(max_w, req_w);
max_h = MAX(max_h, req_h);
}
msg->reqsize.w = MAX(msg->reqsize.w,
this->border_width.l + max_w + this->border_width.r);
msg->reqsize.h += max_h;
}
return true;
}
case JM_SIGNAL:
if (msg->signal.num == JI_SIGNAL_INIT_THEME) {
int w = 0, h = 0;
@ -216,3 +187,32 @@ bool PopupWindow::onProcessMessage(JMessage msg)
return Frame::onProcessMessage(msg);
}
void PopupWindow::onPreferredSize(PreferredSizeEvent& ev)
{
Size resultSize(0, 0);
_ji_theme_textbox_draw(NULL, this, &resultSize.w, &resultSize.h, 0, 0);
resultSize.h = this->border_width.t + this->border_width.b;
if (!jlist_empty(this->children)) {
Size maxSize(0, 0);
Size reqSize;
JWidget child;
JLink link;
JI_LIST_FOR_EACH(this->children, link) {
child = (JWidget)link->data;
reqSize = child->getPreferredSize();
maxSize.w = MAX(maxSize.w, reqSize.w);
maxSize.h = MAX(maxSize.h, reqSize.h);
}
resultSize.w = MAX(resultSize.w, this->border_width.l + maxSize.w + this->border_width.r);
resultSize.h += maxSize.h;
}
ev.setPreferredSize(resultSize);
}

View File

@ -48,6 +48,7 @@ public:
protected:
bool onProcessMessage(JMessage msg);
void onPreferredSize(PreferredSizeEvent& ev);
};
#endif

View File

@ -36,6 +36,7 @@
#include "jinete/jrect.h"
#include "jinete/jtheme.h"
#include "jinete/jwidget.h"
#include "Vaca/Size.h"
static bool separator_msg_proc(JWidget widget, JMessage msg);
@ -56,25 +57,24 @@ static bool separator_msg_proc(JWidget widget, JMessage msg)
switch (msg->type) {
case JM_REQSIZE: {
int max_w, max_h;
int req_w, req_h;
Size maxSize(0, 0);
Size reqSize;
JWidget child;
JLink link;
max_w = max_h = 0;
JI_LIST_FOR_EACH(widget->children, link) {
child = (JWidget)link->data;
jwidget_request_size(child, &req_w, &req_h);
max_w = MAX(max_w, req_w);
max_h = MAX(max_h, req_h);
reqSize = child->getPreferredSize();
maxSize.w = MAX(maxSize.w, reqSize.w);
maxSize.h = MAX(maxSize.h, reqSize.h);
}
if (widget->hasText())
max_w = MAX(max_w, jwidget_get_text_length(widget));
maxSize.w = MAX(maxSize.w, jwidget_get_text_length(widget));
msg->reqsize.w = widget->border_width.l + max_w + widget->border_width.r;
msg->reqsize.h = widget->border_width.t + max_h + widget->border_width.b;
msg->reqsize.w = widget->border_width.l + maxSize.w + widget->border_width.r;
msg->reqsize.h = widget->border_width.t + maxSize.h + widget->border_width.b;
return true;
}

View File

@ -23,6 +23,8 @@
#include "jinete/jinete.h"
#include "jinete/jintern.h"
#include "Vaca/Size.h"
#include "Vaca/PreferredSizeEvent.h"
typedef struct TipData
{
@ -210,37 +212,6 @@ bool TipWindow::onProcessMessage(JMessage msg)
}
break;
case JM_REQSIZE: {
int w = 0, h = 0;
_ji_theme_textbox_draw(NULL, this, &w, &h, 0, 0);
msg->reqsize.w = w;
msg->reqsize.h = this->border_width.t + this->border_width.b;
if (!jlist_empty(this->children)) {
int max_w, max_h;
int req_w, req_h;
JWidget child;
JLink link;
max_w = max_h = 0;
JI_LIST_FOR_EACH(this->children, link) {
child = (JWidget)link->data;
jwidget_request_size(child, &req_w, &req_h);
max_w = MAX(max_w, req_w);
max_h = MAX(max_h, req_h);
}
msg->reqsize.w = MAX(msg->reqsize.w,
this->border_width.l + max_w + this->border_width.r);
msg->reqsize.h += max_h;
}
return true;
}
case JM_SIGNAL:
if (msg->signal.num == JI_SIGNAL_INIT_THEME) {
int w = 0, h = 0;
@ -325,3 +296,32 @@ bool TipWindow::onProcessMessage(JMessage msg)
return Frame::onProcessMessage(msg);
}
void TipWindow::onPreferredSize(PreferredSizeEvent& ev)
{
Size resultSize(0, 0);
_ji_theme_textbox_draw(NULL, this, &resultSize.w, &resultSize.h, 0, 0);
resultSize.h = this->border_width.t + this->border_width.b;
if (!jlist_empty(this->children)) {
Size maxSize(0, 0);
Size reqSize;
JWidget child;
JLink link;
JI_LIST_FOR_EACH(this->children, link) {
child = (JWidget)link->data;
reqSize = child->getPreferredSize();
maxSize.w = MAX(maxSize.w, reqSize.w);
maxSize.h = MAX(maxSize.h, reqSize.h);
}
resultSize.w = MAX(resultSize.w, this->border_width.l + maxSize.w + this->border_width.r);
resultSize.h += maxSize.h;
}
ev.setPreferredSize(resultSize);
}

View File

@ -49,6 +49,7 @@ public:
protected:
bool onProcessMessage(JMessage msg);
void onPreferredSize(PreferredSizeEvent& ev);
};
void jwidget_add_tooltip_text(Widget* widget, const char *text);

View File

@ -40,6 +40,7 @@
#include "jinete/jtheme.h"
#include "jinete/jview.h"
#include "jinete/jwidget.h"
#include "Vaca/Size.h"
#define BAR_SIZE widget->theme->scrollbar_size
@ -353,9 +354,9 @@ static bool view_msg_proc(JWidget widget, JMessage msg)
case JM_REQSIZE: {
View* view = reinterpret_cast<View*>(jwidget_get_data(widget, JI_VIEW));
jwidget_request_size(view->viewport,
&msg->reqsize.w,
&msg->reqsize.h);
Size viewSize = view->viewport->getPreferredSize();
msg->reqsize.w = viewSize.w;
msg->reqsize.h = viewSize.h;
msg->reqsize.w += widget->border_width.l + widget->border_width.r;
msg->reqsize.h += widget->border_width.t + widget->border_width.b;
@ -426,23 +427,23 @@ static bool viewport_msg_proc(JWidget widget, JMessage msg)
static void viewport_needed_size(JWidget widget, int *w, int *h)
{
int req_h, req_w;
Size reqSize;
JLink link;
*w = *h = 0;
JI_LIST_FOR_EACH(widget->children, link) {
jwidget_request_size((JWidget)link->data, &req_w, &req_h);
reqSize = ((Widget*)link->data)->getPreferredSize();
*w = MAX(*w, req_w);
*h = MAX(*h, req_h);
*w = MAX(*w, reqSize.w);
*h = MAX(*h, reqSize.h);
}
}
static void viewport_set_position(JWidget widget, JRect rect)
{
int scroll_x, scroll_y;
int req_h, req_w;
Size reqSize;
JWidget child;
JRect cpos;
JLink link;
@ -457,16 +458,15 @@ static void viewport_set_position(JWidget widget, JRect rect)
JI_LIST_FOR_EACH(widget->children, link) {
child = (JWidget)link->data;
reqSize = child->getPreferredSize();
jwidget_request_size(child, &req_w, &req_h);
cpos->x2 = cpos->x1 + MAX(reqSize.w, jrect_w(widget->rc)
- widget->border_width.l
- widget->border_width.r);
cpos->x2 = cpos->x1 + MAX(req_w, jrect_w(widget->rc)
- widget->border_width.l
- widget->border_width.r);
cpos->y2 = cpos->y1 + MAX(req_h, jrect_h(widget->rc)
- widget->border_width.t
- widget->border_width.b);
cpos->y2 = cpos->y1 + MAX(reqSize.h, jrect_h(widget->rc)
- widget->border_width.t
- widget->border_width.b);
jwidget_set_rect(child, cpos);
}

View File

@ -49,6 +49,7 @@
#include "jinete/jinete.h"
#include "jinete/jintern.h"
#include "Vaca/PreferredSizeEvent.h"
int ji_register_widget_type()
{
@ -95,6 +96,8 @@ Widget::Widget(int type)
this->user_data[1] = NULL;
this->user_data[2] = NULL;
this->user_data[3] = NULL;
m_preferredSize = NULL;
}
void jwidget_free(JWidget widget)
@ -144,6 +147,9 @@ Widget::~Widget()
jhook_free(reinterpret_cast<JHook>(link->data));
jlist_free(this->hooks);
// Delete the preferred size
delete m_preferredSize;
/* low level free */
_ji_remove_widget(this);
}
@ -704,19 +710,6 @@ void Widget::setBounds(const Rect& rc)
jwidget_set_rect(this, &jrc);
}
void jwidget_request_size(JWidget widget, int *w, int *h)
{
JMessage msg;
assert_valid_widget(widget);
msg = jmessage_new(JM_REQSIZE);
jwidget_send_message(widget, msg);
*w = MID(widget->min_w, msg->reqsize.w, widget->max_w);
*h = MID(widget->min_h, msg->reqsize.h, widget->max_h);
jmessage_free(msg);
}
void jwidget_relayout(JWidget widget)
{
jwidget_set_rect(widget, widget->rc);
@ -1308,6 +1301,76 @@ void Widget::closeWindow()
frame->closeWindow(this);
}
// ===============================================================
// SIZE & POSITION
// ===============================================================
/**
Returns the preferred size of the Widget.
It checks if the preferred size is static (it means when it was
set through #setPreferredSize before) or if it is dynamic (this is
the default and is when the #onPreferredSize is used to determined
the preferred size).
In another words, if you do not use #setPreferredSize to set a
<em>static preferred size</em> for the widget then #onPreferredSize
will be used to calculate it.
@see setPreferredSize, onPreferredSize, #getPreferredSize(const Size &)
*/
Size Widget::getPreferredSize()
{
if (m_preferredSize != NULL)
return *m_preferredSize;
else {
PreferredSizeEvent ev(this, Size(0, 0));
onPreferredSize(ev);
return ev.getPreferredSize();
}
}
/**
Returns the preferred size trying to fit in the specified size.
Remember that if you use #setPreferredSize this routine will
return the static size which you specified manually.
@param fitIn
This can have both attributes (width and height) in
zero, which means that it'll behave same as #getPreferredSize().
If the width is great than zero the #onPreferredSize will try to
fit in that width (this is useful to fit @link Vaca::Label Label@endlink
or @link Vaca::Edit Edit@endlink controls in a specified width and
calculate the height it could occupy).
@see getPreferredSize
*/
Size Widget::getPreferredSize(const Size& fitIn)
{
if (m_preferredSize != NULL)
return *m_preferredSize;
else {
PreferredSizeEvent ev(this, fitIn);
onPreferredSize(ev);
return ev.getPreferredSize();
}
}
/**
Sets a fixed preferred size specified by the user.
Widget::getPreferredSize() will return this value if it's setted.
*/
void Widget::setPreferredSize(const Size& fixedSize)
{
delete m_preferredSize;
m_preferredSize = new Size(fixedSize);
}
void Widget::setPreferredSize(int fixedWidth, int fixedHeight)
{
setPreferredSize(Size(fixedWidth, fixedHeight));
}
// ===============================================================
// FOCUS & MOUSE
// ===============================================================
@ -1503,3 +1566,29 @@ bool Widget::onProcessMessage(JMessage msg)
return false;
}
// ===============================================================
// EVENTS
// ===============================================================
/**
Calculates the preferred size for the widget.
The default implementation get the preferred size of the current
layout manager. Also, if there exists layout-free widgets inside
this parent (like a StatusBar), they preferred-sizes are
accumulated.
@see Layout#getPreferredSize,
*/
void Widget::onPreferredSize(PreferredSizeEvent& ev)
{
JMessage msg = jmessage_new(JM_REQSIZE);
jwidget_send_message(this, msg);
Size sz(msg->reqsize.w, msg->reqsize.h);
sz.w = MID(this->min_w, sz.w, this->max_w);
sz.h = MID(this->min_h, sz.h, this->max_h);
jmessage_free(msg);
ev.setPreferredSize(sz);
}

View File

@ -39,6 +39,8 @@
#include "Vaca/Rect.h"
#include "Vaca/Widget.h"
namespace Vaca { class PreferredSizeEvent; }
#ifndef NDEBUG
#include "jinete/jintern.h"
#define assert_valid_widget(widget) assert((widget) != NULL && \
@ -48,6 +50,8 @@
#endif
using Vaca::Rect;
using Vaca::Size;
using Vaca::PreferredSizeEvent;
struct FONT;
struct BITMAP;
@ -101,7 +105,6 @@ bool jwidget_has_child(JWidget widget, JWidget child);
/* position and geometry */
void jwidget_request_size(JWidget widget, int *w, int *h);
void jwidget_relayout(JWidget widget);
JRect jwidget_get_rect(JWidget widget);
JRect jwidget_get_child_rect(JWidget widget);
@ -292,6 +295,15 @@ public:
bool sendMessage(JMessage msg);
void closeWindow();
// ===============================================================
// SIZE & POSITION
// ===============================================================
Size getPreferredSize();
Size getPreferredSize(const Size& fitIn);
void setPreferredSize(const Size& fixedSize);
void setPreferredSize(int fixedWidth, int fixedHeight);
// ===============================================================
// FOCUS & MOUSE
// ===============================================================
@ -306,8 +318,21 @@ public:
bool hasCapture();
protected:
// ===============================================================
// MESSAGE PROCESSING
// ===============================================================
virtual bool onProcessMessage(JMessage msg);
// ===============================================================
// EVENTS
// ===============================================================
virtual void onPreferredSize(PreferredSizeEvent& ev);
private:
Size* m_preferredSize;
};
#endif

View File

@ -38,6 +38,8 @@
#include "jinete/jinete.h"
#include "jinete/jintern.h"
#include "Vaca/Size.h"
#include "Vaca/PreferredSizeEvent.h"
enum {
WINDOW_NONE = 0,
@ -115,7 +117,7 @@ void Frame::set_wantfocus(bool state)
void Frame::remap_window()
{
int req_w, req_h;
Size reqSize;
JRect rect;
if (m_is_autoremap) {
@ -123,11 +125,11 @@ void Frame::remap_window()
this->setVisible(true);
}
jwidget_request_size(this, &req_w, &req_h);
reqSize = this->getPreferredSize();
rect = jrect_new(this->rc->x1, this->rc->y1,
this->rc->x1+req_w,
this->rc->y1+req_h);
this->rc->x1+reqSize.w,
this->rc->y1+reqSize.h);
jwidget_set_rect(this, rect);
jrect_free(rect);
@ -242,10 +244,6 @@ bool Frame::onProcessMessage(JMessage msg)
{
switch (msg->type) {
case JM_REQSIZE:
this->window_request_size(&msg->reqsize.w, &msg->reqsize.h);
return true;
case JM_SETPOS:
this->window_set_position(&msg->setpos.rect);
return true;
@ -412,39 +410,38 @@ bool Frame::onProcessMessage(JMessage msg)
return Widget::onProcessMessage(msg);
}
void Frame::window_request_size(int *w, int *h)
void Frame::onPreferredSize(PreferredSizeEvent& ev)
{
JWidget manager = getManager();
if (m_is_desktop) {
JRect cpos = jwidget_get_child_rect(manager);
*w = jrect_w(cpos);
*h = jrect_h(cpos);
ev.setPreferredSize(jrect_w(cpos),
jrect_h(cpos));
jrect_free(cpos);
}
else {
int max_w, max_h;
int req_w, req_h;
Size maxSize(0, 0);
Size reqSize;
JWidget child;
JLink link;
max_w = max_h = 0;
JI_LIST_FOR_EACH(this->children, link) {
child = (JWidget)link->data;
if (!jwidget_is_decorative(child)) {
jwidget_request_size(child, &req_w, &req_h);
reqSize = child->getPreferredSize();
max_w = MAX(max_w, req_w);
max_h = MAX(max_h, req_h);
maxSize.w = MAX(maxSize.w, reqSize.w);
maxSize.h = MAX(maxSize.h, reqSize.h);
}
}
if (this->hasText())
max_w = MAX(max_w, jwidget_get_text_length(this));
maxSize.w = MAX(maxSize.w, jwidget_get_text_length(this));
*w = this->border_width.l + max_w + this->border_width.r;
*h = this->border_width.t + max_h + this->border_width.b;
ev.setPreferredSize(this->border_width.l + maxSize.w + this->border_width.r,
this->border_width.t + maxSize.h + this->border_width.b);
}
}
@ -546,10 +543,6 @@ int Frame::get_action(int x, int y)
void Frame::limit_size(int *w, int *h)
{
int req_w, req_h;
jwidget_request_size(this, &req_w, &req_h);
*w = MAX(*w, this->border_width.l+this->border_width.r);
*h = MAX(*h, this->border_width.t+this->border_width.b);
}

View File

@ -83,9 +83,9 @@ public:
protected:
bool onProcessMessage(JMessage msg);
void onPreferredSize(PreferredSizeEvent& ev);
private:
void window_request_size(int* w, int* h);
void window_set_position(JRect rect);
int get_action(int x, int y);
void limit_size(int* w, int* h);

61
third_party/vaca/include/Vaca/Event.h vendored Normal file
View File

@ -0,0 +1,61 @@
// Vaca - Visual Application Components Abstraction
// Copyright (c) 2005-2010 David Capello
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// * Neither the name of the author nor the names of its contributors
// may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef VACA_EVENT_H
#define VACA_EVENT_H
#include "Vaca/base.h"
namespace Vaca {
/**
Base class for every kind of event.
*/
class VACA_DLL Event
{
/**
The component which generates the event. It's specified in the
@link Event#Event(Component*) Event's constructor@endlink
*/
Component* m_source;
public:
Event(Component* source);
virtual ~Event();
Component* getSource();
};
} // namespace Vaca
#endif // VACA_EVENT_H

View File

@ -0,0 +1,63 @@
// Vaca - Visual Application Components Abstraction
// Copyright (c) 2005-2010 David Capello
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// * Neither the name of the author nor the names of its contributors
// may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef VACA_PREFERREDSIZEEVENT_H
#define VACA_PREFERREDSIZEEVENT_H
#include "Vaca/base.h"
#include "Vaca/Event.h"
#include "Vaca/Size.h"
namespace Vaca {
class VACA_DLL PreferredSizeEvent : public Event
{
Size m_fitIn;
Size m_preferredSize;
public:
PreferredSizeEvent(Widget* source, const Size& fitIn);
virtual ~PreferredSizeEvent();
Size fitInSize() const;
int fitInWidth() const;
int fitInHeight() const;
Size getPreferredSize() const;
void setPreferredSize(const Size& preferredSize);
void setPreferredSize(int w, int h);
};
} // namespace Vaca
#endif // VACA_PREFERREDSIZEEVENT_H

64
third_party/vaca/src/Event.cpp vendored Normal file
View File

@ -0,0 +1,64 @@
// Vaca - Visual Application Components Abstraction
// Copyright (c) 2005-2010 David Capello
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// * Neither the name of the author nor the names of its contributors
// may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Vaca/Event.h"
using namespace Vaca;
/**
Creates a new event specifying that it was generated
from the @a source component.
@param source
The component which generates the event.
*/
Event::Event(Component* source)
: m_source(source)
{
}
/**
Destroys the event.
*/
Event::~Event()
{
}
/**
Returns the event's source.
@return
The component which generates the event.
*/
Component* Event::getSource()
{
return m_source;
}

View File

@ -0,0 +1,94 @@
// Vaca - Visual Application Components Abstraction
// Copyright (c) 2005-2010 David Capello
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// * Neither the name of the author nor the names of its contributors
// may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Vaca/PreferredSizeEvent.h"
#include "Vaca/Widget.h"
using namespace Vaca;
/**
Event generated to calculate the preferred size of a widget.
@param source
The widget that want to know its preferred size.
@param fitIn
This could be Size(0, 0) that means calculate the preferred size
without restrictions. If its width or height is greater than 0,
you could try to fit your widget to that width or height.
*/
PreferredSizeEvent::PreferredSizeEvent(Widget* source, const Size& fitIn)
: Event(source)
, m_fitIn(fitIn)
, m_preferredSize(0, 0)
{
}
/**
Destroys the PreferredSizeEvent.
*/
PreferredSizeEvent::~PreferredSizeEvent()
{
}
Size PreferredSizeEvent::fitInSize() const
{
return m_fitIn;
}
int PreferredSizeEvent::fitInWidth() const
{
return m_fitIn.w;
}
int PreferredSizeEvent::fitInHeight() const
{
return m_fitIn.h;
}
Size PreferredSizeEvent::getPreferredSize() const
{
return m_preferredSize;
}
void PreferredSizeEvent::setPreferredSize(const Size& preferredSize)
{
m_preferredSize = preferredSize;
}
/**
Sets the preferred size for the widget.
*/
void PreferredSizeEvent::setPreferredSize(int w, int h)
{
m_preferredSize.w = w;
m_preferredSize.h = h;
}