Replace ui::jregion with gfx::Region class

This is an old TODO item, and it's the first step to finally
get rid of JRect and struct jrect.
This commit is contained in:
David Capello 2013-01-13 22:39:44 -03:00
parent 6332b1a6e5
commit eacd0c7642
32 changed files with 357 additions and 3263 deletions

View File

@ -53,7 +53,6 @@
* About Signals/Slots: Add some field in slots to avoid disconnecting * About Signals/Slots: Add some field in slots to avoid disconnecting
them from dead signals. them from dead signals.
* Replace JRect & jrect with gfx::Rect. * Replace JRect & jrect with gfx::Rect.
* Create gfx::Region to replace JRegion & jregion.
* editors_ -> MultiEditors class widget * editors_ -> MultiEditors class widget
* convert all widgets to classes: * convert all widgets to classes:
* match UI library design with Vaca library. * match UI library design with Vaca library.

View File

@ -32,7 +32,6 @@
#include "raster/stock.h" #include "raster/stock.h"
#include "ui/manager.h" #include "ui/manager.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "ui/region.h"
#include "ui/view.h" #include "ui/view.h"
#include "ui/widget.h" #include "ui/widget.h"
#include "undo_transaction.h" #include "undo_transaction.h"
@ -256,28 +255,21 @@ void FilterManagerImpl::applyToTarget()
void FilterManagerImpl::flush() void FilterManagerImpl::flush()
{ {
if (m_row >= 0) { if (m_row >= 0) {
JRegion reg1, reg2; gfx::Rect rect;
struct jrect rect;
Editor* editor = current_editor; Editor* editor = current_editor;
reg1 = jregion_new(NULL, 0);
editor->editorToScreen(m_x+m_offset_x, editor->editorToScreen(m_x+m_offset_x,
m_y+m_offset_y+m_row-1, m_y+m_offset_y+m_row-1,
&rect.x1, &rect.y1); &rect.x, &rect.y);
rect.x2 = rect.x1 + (m_w << editor->getZoom()); rect.w = (m_w << editor->getZoom());
rect.y2 = rect.y1 + (1 << editor->getZoom()); rect.h = (1 << editor->getZoom());
reg2 = jregion_new(&rect, 1); gfx::Region reg1(rect);
jregion_union(reg1, reg1, reg2); gfx::Region reg2;
jregion_free(reg2); editor->getDrawableRegion(reg2, Widget::kCutTopWindows);
reg1.createIntersection(reg1, reg2);
reg2 = jwidget_get_drawable_region(editor, JI_GDR_CUTTOPWINDOWS);
jregion_intersect(reg1, reg1, reg2);
jregion_free(reg2);
editor->invalidateRegion(reg1); editor->invalidateRegion(reg1);
jregion_free(reg1);
} }
} }

View File

@ -1383,10 +1383,10 @@ void AnimationEditor::setScroll(int x, int y, bool use_refresh_region)
int old_scroll_y = 0; int old_scroll_y = 0;
int max_scroll_x; int max_scroll_x;
int max_scroll_y; int max_scroll_y;
JRegion region = NULL; Region region;
if (use_refresh_region) { if (use_refresh_region) {
region = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); getDrawableRegion(region, kCutTopWindows);
old_scroll_x = m_scroll_x; old_scroll_x = m_scroll_x;
old_scroll_y = m_scroll_y; old_scroll_y = m_scroll_y;
} }
@ -1404,51 +1404,36 @@ void AnimationEditor::setScroll(int x, int y, bool use_refresh_region)
int new_scroll_y = m_scroll_y; int new_scroll_y = m_scroll_y;
int dx = old_scroll_x - new_scroll_x; int dx = old_scroll_x - new_scroll_x;
int dy = old_scroll_y - new_scroll_y; int dy = old_scroll_y - new_scroll_y;
JRegion reg1 = jregion_new(NULL, 0); Rect rect2;
JRegion reg2 = jregion_new(NULL, 0); Region reg1;
JRect rect2 = jrect_new(0, 0, 0, 0);
jmouse_hide(); jmouse_hide();
// Scroll layers. // Scroll layers.
jrect_replace(rect2, rect2 = Rect(this->rc->x1,
this->rc->x1,
this->rc->y1 + HDRSIZE, this->rc->y1 + HDRSIZE,
this->rc->x1 + m_separator_x, m_separator_x,
this->rc->y2); this->rc->y2 - (this->rc->y1 + HDRSIZE));
jregion_reset(reg2, rect2); reg1.createIntersection(region, Region(rect2));
jregion_copy(reg1, region); scrollRegion(reg1, 0, dy);
jregion_intersect(reg1, reg1, reg2);
this->scrollRegion(reg1, 0, dy);
// Scroll header-frame. // Scroll header-frame.
jrect_replace(rect2, rect2 = Rect(this->rc->x1 + m_separator_x + m_separator_w,
this->rc->x1 + m_separator_x + m_separator_w,
this->rc->y1, this->rc->y1,
this->rc->x2, this->rc->x2 - (this->rc->x1 + m_separator_x + m_separator_w),
this->rc->y1 + HDRSIZE); HDRSIZE);
jregion_reset(reg2, rect2); reg1.createIntersection(region, Region(rect2));
jregion_copy(reg1, region); scrollRegion(reg1, dx, 0);
jregion_intersect(reg1, reg1, reg2);
this->scrollRegion(reg1, dx, 0);
// Scroll cels. // Scroll cels.
jrect_replace(rect2, rect2 = Rect(this->rc->x1 + m_separator_x + m_separator_w,
this->rc->x1 + m_separator_x + m_separator_w,
this->rc->y1 + HDRSIZE, this->rc->y1 + HDRSIZE,
this->rc->x2, this->rc->x2 - (this->rc->x1 + m_separator_x + m_separator_w),
this->rc->y2); this->rc->y2 - (this->rc->y1 + HDRSIZE));
jregion_reset(reg2, rect2); reg1.createIntersection(region, Region(rect2));
jregion_copy(reg1, region); scrollRegion(reg1, dx, dy);
jregion_intersect(reg1, reg1, reg2);
this->scrollRegion(reg1, dx, dy);
jmouse_show(); jmouse_show();
jregion_free(region);
jregion_free(reg1);
jregion_free(reg2);
jrect_free(rect2);
} }
} }

View File

@ -577,7 +577,7 @@ Cursor* SkinTheme::getCursor(CursorType type)
} }
} }
void SkinTheme::init_widget(Widget* widget) void SkinTheme::initWidget(Widget* widget)
{ {
#define BORDER(n) \ #define BORDER(n) \
widget->border_width.l = (n); \ widget->border_width.l = (n); \
@ -781,12 +781,12 @@ void SkinTheme::init_widget(Widget* widget)
} }
} }
JRegion SkinTheme::get_window_mask(Widget* widget) void SkinTheme::getWindowMask(Widget* widget, Region& region)
{ {
return jregion_new(widget->rc, 1); region = widget->getBounds();
} }
void SkinTheme::map_decorative_widget(Widget* widget) void SkinTheme::mapDecorativeWidget(Widget* widget)
{ {
if (widget->getId() == kThemeCloseButtonId) { if (widget->getId() == kThemeCloseButtonId) {
Widget* window = widget->getParent(); Widget* window = widget->getParent();

View File

@ -119,9 +119,9 @@ public:
void reload_fonts(); void reload_fonts();
ui::Cursor* getCursor(ui::CursorType type); ui::Cursor* getCursor(ui::CursorType type);
void init_widget(ui::Widget* widget); void initWidget(ui::Widget* widget);
ui::JRegion get_window_mask(ui::Widget* widget); void getWindowMask(ui::Widget* widget, gfx::Region& region);
void map_decorative_widget(ui::Widget* widget); void mapDecorativeWidget(ui::Widget* widget);
void paintDesktop(ui::PaintEvent& ev); void paintDesktop(ui::PaintEvent& ev);
void paintBox(ui::PaintEvent& ev); void paintBox(ui::PaintEvent& ev);

View File

@ -36,7 +36,6 @@ add_library(ui-lib
preferred_size_event.cpp preferred_size_event.cpp
property.cpp property.cpp
rect.cpp rect.cpp
region.cpp
scroll_bar.cpp scroll_bar.cpp
separator.cpp separator.cpp
slider.cpp slider.cpp

View File

@ -32,7 +32,6 @@
namespace ui { namespace ui {
struct jrect; struct jrect;
struct jregion;
// Alignment. // Alignment.
#define JI_HORIZONTAL 0x0001 #define JI_HORIZONTAL 0x0001
@ -134,14 +133,9 @@ namespace ui {
JM_REGISTERED_MESSAGES JM_REGISTERED_MESSAGES
}; };
// Flags for jwidget_get_drawable_region.
#define JI_GDR_CUTTOPWINDOWS 1 // Cut areas where are windows on top.
#define JI_GDR_USECHILDAREA 2 // Use areas where are children.
typedef unsigned int JID; typedef unsigned int JID;
typedef struct jrect* JRect; typedef struct jrect* JRect;
typedef struct jregion* JRegion;
class GuiSystem { class GuiSystem {
public: public:

View File

@ -14,7 +14,6 @@
#include "ui/font.h" #include "ui/font.h"
#include "ui/intern.h" #include "ui/intern.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "ui/region.h"
#include "ui/system.h" #include "ui/system.h"
#include "ui/widget.h" #include "ui/widget.h"
@ -154,33 +153,33 @@ void jdraw_text(BITMAP* bmp, FONT* font, const char *s, int x, int y,
} }
} }
void ji_move_region(JRegion region, int dx, int dy) void ji_move_region(const Region& region, int dx, int dy)
{ {
int c, nrects = JI_REGION_NUM_RECTS(region); size_t nrects = region.size();
JRect rc;
// Blit directly screen to screen. // Blit directly screen to screen.
if (is_linear_bitmap(ji_screen) && nrects == 1) { if (is_linear_bitmap(ji_screen) && nrects == 1) {
rc = JI_REGION_RECTS(region); Rect rc = region[0];
blit(ji_screen, ji_screen, blit(ji_screen, ji_screen, rc.x, rc.y, rc.x+dx, rc.y+dy, rc.w, rc.h);
rc->x1, rc->y1,
rc->x1+dx, rc->y1+dy, jrect_w(rc), jrect_h(rc));
} }
// Blit saving areas and copy them. // Blit saving areas and copy them.
else if (nrects > 1) { else if (nrects > 1) {
std::vector<BITMAP*> images(nrects); std::vector<BITMAP*> images(nrects);
Region::const_iterator it, begin=region.begin(), end=region.end();
BITMAP* bmp; BITMAP* bmp;
int c;
for (c=0, rc=JI_REGION_RECTS(region); c<nrects; ++c, ++rc) { for (c=0, it=begin; it != end; ++it, ++c) {
bmp = create_bitmap(jrect_w(rc), jrect_h(rc)); const Rect& rc = *it;
blit(ji_screen, bmp, bmp = create_bitmap(rc.w, rc.h);
rc->x1, rc->y1, 0, 0, bmp->w, bmp->h); blit(ji_screen, bmp, rc.x, rc.y, 0, 0, bmp->w, bmp->h);
images[c] = bmp; images[c] = bmp;
} }
for (c=0, rc=JI_REGION_RECTS(region); c<nrects; ++c, ++rc) { for (c=0, it=begin; it != end; ++it, ++c) {
const Rect& rc = *it;
bmp = images[c]; bmp = images[c];
blit(bmp, ji_screen, 0, 0, rc->x1+dx, rc->y1+dy, bmp->w, bmp->h); blit(bmp, ji_screen, 0, 0, rc.x+dx, rc.y+dy, bmp->w, bmp->h);
destroy_bitmap(bmp); destroy_bitmap(bmp);
} }
} }

View File

@ -8,6 +8,7 @@
#define UI_DRAW_H_INCLUDED #define UI_DRAW_H_INCLUDED
#include "gfx/rect.h" #include "gfx/rect.h"
#include "gfx/region.h"
#include "ui/base.h" #include "ui/base.h"
#include "ui/color.h" #include "ui/color.h"
@ -34,7 +35,7 @@ namespace ui {
void jdraw_inverted_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); void jdraw_inverted_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y);
void ji_move_region(JRegion region, int dx, int dy); void ji_move_region(const gfx::Region& region, int dx, int dy);
} // namespace ui } // namespace ui

View File

@ -44,7 +44,6 @@
#include "ui/preferred_size_event.h" #include "ui/preferred_size_event.h"
#include "ui/property.h" #include "ui/property.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "ui/region.h"
#include "ui/save_layout_event.h" #include "ui/save_layout_event.h"
#include "ui/scroll_bar.h" #include "ui/scroll_bar.h"
#include "ui/separator.h" #include "ui/separator.h"

View File

@ -824,15 +824,13 @@ void Manager::_openWindow(Window* window)
void Manager::_closeWindow(Window* window, bool redraw_background) void Manager::_closeWindow(Window* window, bool redraw_background)
{ {
Message* msg; Message* msg;
JRegion reg1; gfx::Region reg1;
if (!hasChild(window)) if (!hasChild(window))
return; return;
if (redraw_background) if (redraw_background)
reg1 = jwidget_get_region(window); window->getRegion(reg1);
else
reg1 = NULL;
// Close all windows to this desktop // Close all windows to this desktop
if (window->is_desktop()) { if (window->is_desktop()) {
@ -841,9 +839,9 @@ void Manager::_closeWindow(Window* window, bool redraw_background)
if (child == window) if (child == window)
break; break;
else { else {
JRegion reg2 = jwidget_get_region(window); gfx::Region reg2;
jregion_union(reg1, reg1, reg2); window->getRegion(reg2);
jregion_free(reg2); reg1.createUnion(reg1, reg2);
_closeWindow(child, false); _closeWindow(child, false);
} }
@ -872,10 +870,7 @@ void Manager::_closeWindow(Window* window, bool redraw_background)
removeChild(window); removeChild(window);
// Redraw background. // Redraw background.
if (reg1) {
invalidateRegion(reg1); invalidateRegion(reg1);
jregion_free(reg1);
}
// Maybe the window is in the "new_windows" list. // Maybe the window is in the "new_windows" list.
WidgetsList::iterator it = WidgetsList::iterator it =
@ -1115,14 +1110,11 @@ void Manager::pumpQueue()
} }
} }
void Manager::invalidateDisplayRegion(const JRegion region) void Manager::invalidateDisplayRegion(const gfx::Region& region)
{ {
JRegion reg1 = jregion_new(NULL, 0); // TODO intersect with getDrawableRegion()???
JRegion reg2 = jregion_new(this->rc, 0); gfx::Region reg1;
JRegion reg3; reg1.createIntersection(region, gfx::Region(getBounds()));
// TODO intersect with jwidget_get_drawable_region()???
jregion_intersect(reg1, region, reg2);
// Redraw windows from top to background. // Redraw windows from top to background.
bool withDesktop = false; bool withDesktop = false;
@ -1139,19 +1131,15 @@ void Manager::invalidateDisplayRegion(const JRegion region)
} }
// Clip this window area for the next window. // Clip this window area for the next window.
reg3 = jwidget_get_region(window); gfx::Region reg3;
jregion_copy(reg2, reg1); window->getRegion(reg3);
jregion_subtract(reg1, reg2, reg3); reg1.createSubtraction(reg1, reg3);
jregion_free(reg3);
} }
// Invalidate areas outside windows (only when there are not a // Invalidate areas outside windows (only when there are not a
// desktop window). // desktop window).
if (!withDesktop) if (!withDesktop)
Widget::invalidateRegion(reg1); Widget::invalidateRegion(reg1);
jregion_free(reg1);
jregion_free(reg2);
} }
LayoutIO* Manager::getLayoutIO() LayoutIO* Manager::getLayoutIO()

View File

@ -64,7 +64,7 @@ namespace ui {
void removeMessageFilter(int message, Widget* widget); void removeMessageFilter(int message, Widget* widget);
void removeMessageFilterFor(Widget* widget); void removeMessageFilterFor(Widget* widget);
void invalidateDisplayRegion(const JRegion region); void invalidateDisplayRegion(const gfx::Region& region);
LayoutIO* getLayoutIO(); LayoutIO* getLayoutIO();

View File

@ -679,11 +679,8 @@ void MenuBox::set_position(JRect rect)
{ {
jrect_copy(this->rc, rect); jrect_copy(this->rc, rect);
if (Menu* menu = getMenu()) { if (Menu* menu = getMenu())
JRect cpos = jwidget_get_child_rect(this); menu->setBounds(getChildrenBounds());
jwidget_set_rect(menu, cpos);
jrect_free(cpos);
}
} }
bool MenuItem::onProcessMessage(Message* msg) bool MenuItem::onProcessMessage(Message* msg)

View File

@ -74,12 +74,6 @@ namespace ui {
struct jrect rect; /* set position */ struct jrect rect; /* set position */
}; };
struct MessageDrawRgn
{
MessageAny any;
JRegion region; /* region to redraw */
};
struct MessageUser struct MessageUser
{ {
MessageAny any; MessageAny any;
@ -96,7 +90,6 @@ namespace ui {
MessageMouse mouse; MessageMouse mouse;
MessageTimer timer; MessageTimer timer;
MessageSetPos setpos; MessageSetPos setpos;
MessageDrawRgn drawrgn;
MessageUser user; MessageUser user;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,6 @@ PopupWindow::PopupWindow(const char* text, bool close_on_buttonpressed)
: Window(false, text) : Window(false, text)
{ {
m_close_on_buttonpressed = close_on_buttonpressed; m_close_on_buttonpressed = close_on_buttonpressed;
m_hot_region = NULL;
m_filtering = false; m_filtering = false;
set_sizeable(false); set_sizeable(false);
@ -40,25 +39,17 @@ PopupWindow::PopupWindow(const char* text, bool close_on_buttonpressed)
PopupWindow::~PopupWindow() PopupWindow::~PopupWindow()
{ {
stopFilteringMessages(); stopFilteringMessages();
if (m_hot_region != NULL)
jregion_free(m_hot_region);
} }
/** /**
* @param region The new hot-region. This pointer is holded by the @a widget. * @param region The new hot-region. This pointer is holded by the @a widget.
* So you cannot destroy it after calling this routine. * So you cannot destroy it after calling this routine.
*/ */
void PopupWindow::setHotRegion(JRegion region) void PopupWindow::setHotRegion(const gfx::Region& region)
{ {
ASSERT(region != NULL);
if (m_hot_region != NULL)
jregion_free(m_hot_region);
startFilteringMessages(); startFilteringMessages();
m_hot_region = region; m_hotRegion = region;
} }
void PopupWindow::makeFloating() void PopupWindow::makeFloating()
@ -82,7 +73,7 @@ bool PopupWindow::onProcessMessage(Message* msg)
break; break;
case JM_MOUSELEAVE: case JM_MOUSELEAVE:
if (m_hot_region == NULL && !is_moveable()) if (m_hotRegion.isEmpty() && !is_moveable())
closeWindow(NULL); closeWindow(NULL);
break; break;
@ -119,13 +110,11 @@ bool PopupWindow::onProcessMessage(Message* msg)
case JM_MOTION: case JM_MOTION:
if (!is_moveable() && if (!is_moveable() &&
m_hot_region != NULL && !m_hotRegion.isEmpty() &&
getManager()->getCapture() == NULL) { getManager()->getCapture() == NULL) {
struct jrect box;
// If the mouse is outside the hot-region we have to close the // If the mouse is outside the hot-region we have to close the
// window. // window.
if (!jregion_point_in(m_hot_region, msg->mouse.x, msg->mouse.y, &box)) if (!m_hotRegion.contains(Point(msg->mouse.x, msg->mouse.y)))
closeWindow(NULL); closeWindow(NULL);
} }
break; break;

View File

@ -18,7 +18,7 @@ namespace ui {
PopupWindow(const char* text, bool close_on_buttonpressed); PopupWindow(const char* text, bool close_on_buttonpressed);
~PopupWindow(); ~PopupWindow();
void setHotRegion(JRegion region); void setHotRegion(const gfx::Region& region);
void makeFloating(); void makeFloating();
void makeFixed(); void makeFixed();
@ -34,7 +34,7 @@ namespace ui {
void stopFilteringMessages(); void stopFilteringMessages();
bool m_close_on_buttonpressed; bool m_close_on_buttonpressed;
JRegion m_hot_region; gfx::Region m_hotRegion;
bool m_filtering; bool m_filtering;
}; };

View File

@ -1,115 +0,0 @@
// ASEPRITE gui library
// Copyright (C) 2001-2012 David Capello
//
// This source file is distributed under a BSD-like license, please
// read LICENSE.txt for more information.
#include "config.h"
#include <allegro.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "base/memory.h"
#include "ui/base.h"
#include "ui/rect.h"
#include "ui/region.h"
namespace ui {
#define xalloc base_malloc
#define xfree base_free
#define xrealloc base_realloc
#define Bool bool
#define BoxRec struct jrect
#define RegDataRec struct jregion_data
#define RegionRec struct jregion
#define BoxPtr JRect
#define RegDataPtr RegDataRec *
#define RegionPtr JRegion
#define NullBox ((JRect)NULL)
#define REGION_NIL(reg) JI_REGION_NIL(reg)
#define REGION_NAR(reg) JI_REGION_NAR(reg)
#define REGION_NUM_RECTS(reg) JI_REGION_NUM_RECTS(reg)
#define REGION_SIZE(reg) JI_REGION_SIZE(reg)
#define REGION_RECTS(reg) JI_REGION_RECTS(reg)
#define REGION_BOXPTR(reg) JI_REGION_RECTPTR(reg)
#define REGION_BOX(reg,i) JI_REGION_RECT(reg,i)
#define REGION_TOP(reg) JI_REGION_TOP(reg)
#define REGION_END(reg) JI_REGION_END(reg)
#define REGION_SZOF(n) JI_REGION_SZOF(n)
#define rgnOUT JI_RGNOUT
#define rgnIN JI_RGNIN
#define rgnPART JI_RGNPART
struct ji_point { int x, y; };
#define DDXPointRec struct ji_point
#define DDXPointPtr DDXPointRec *
#if !defined(MAXSHORT) || !defined(MINSHORT) || \
!defined(MAXINT) || !defined(MININT)
/*
* Some implementations #define these through <math.h>, so preclude
* #include'ing it later.
*/
#include <math.h>
#endif
#undef MAXSHORT
#define MAXSHORT SHRT_MAX
#undef MINSHORT
#define MINSHORT SHRT_MIN
#undef MAXINT
#define MAXINT INT_MAX
#undef MININT
#define MININT INT_MIN
// min/max macros
#ifndef min
#define min MIN
#endif
#ifndef max
#define max MAX
#endif
#define miBrokenData ji_broken_data
#define miBrokenRegion ji_broken_region
#define miRegionCreate jregion_new
#define miRegionInit jregion_init
#define miRegionDestroy jregion_free
#define miRegionUninit jregion_uninit
#define miRegionCopy jregion_copy
#define miIntersect jregion_intersect
#define miUnion jregion_union
#define miRegionAppend jregion_append
#define miRegionValidate jregion_validate
/* JRegion jrects_to_region(int nrects, JRect *prect, int ctype); */
#define miSubtract jregion_subtract
#define miInverse jregion_inverse
#define miRectIn jregion_rect_in
#define miTranslateRegion jregion_translate
#define miRegionReset jregion_reset
#define miRegionBreak jregion_break
#define miPointInRegion jregion_point_in
#define miRegionEqual jregion_equal
#define miRegionNotEmpty jregion_notempty
#define miRegionEmpty jregion_empty
#define miRegionExtents jregion_extents
#undef assert
#define assert ASSERT
#include "miregion.cpp"
} // namespace ui

View File

@ -1,78 +0,0 @@
// ASEPRITE gui library
// Copyright (C) 2001-2012 David Capello
//
// This source file is distributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef UI_REGION_H_INCLUDED
#define UI_REGION_H_INCLUDED
#include "ui/rect.h"
namespace ui {
#define JI_REGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
/* not a region */
#define JI_REGION_NAR(reg) ((reg)->data == &ji_broken_data)
#define JI_REGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
#define JI_REGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
#define JI_REGION_RECTS(reg) ((reg)->data ? (JRect)((reg)->data + 1) \
: &(reg)->extents)
#define JI_REGION_RECTPTR(reg) ((JRect)((reg)->data + 1))
#define JI_REGION_RECT(reg,i) (&JI_REGION_RECTPTR(reg)[i])
#define JI_REGION_TOP(reg) JI_REGION_RECT(reg, (reg)->data->numRects)
#define JI_REGION_END(reg) JI_REGION_RECT(reg, (reg)->data->numRects - 1)
#define JI_REGION_SZOF(n) (sizeof(struct jregion_data) + ((n) * sizeof(struct jrect)))
/* return values from jregion_rect_in */
#define JI_RGNOUT 0
#define JI_RGNIN 1
#define JI_RGNPART 2
struct jregion_data
{
int size;
int numRects;
/* struct jrect rects[size]; */
};
struct jregion
{
struct jrect extents;
struct jregion_data *data;
};
extern struct jregion_data ji_broken_data;
extern struct jregion ji_broken_region;
JRegion jregion_new(JRect rect, int size);
void jregion_init(JRegion reg, JRect rect, int size);
void jregion_free(JRegion reg);
void jregion_uninit(JRegion reg);
bool jregion_copy(JRegion dst, JRegion src);
bool jregion_intersect(JRegion newrgn, JRegion reg1, JRegion reg2);
bool jregion_union(JRegion newrgn, JRegion reg1, JRegion reg2);
bool jregion_append(JRegion dstrgn, JRegion rgn);
bool jregion_validate(JRegion badreg, bool *overlap);
/* JRegion jrects_to_region(int nrects, JRect *prect, int ctype); */
bool jregion_subtract(JRegion regD, JRegion regM, JRegion regS);
bool jregion_inverse(JRegion newReg, JRegion reg1, JRect invRect);
int jregion_rect_in(JRegion region, JRect rect);
void jregion_translate(JRegion reg, int x, int y);
void jregion_reset(JRegion reg, JRect box);
bool jregion_break(JRegion reg);
bool jregion_point_in(JRegion reg, int x, int y, JRect box);
bool jregion_equal(JRegion reg1, JRegion reg2);
bool jregion_notempty(JRegion reg);
void jregion_empty(JRegion reg);
JRect jregion_extents(JRegion reg);
} // namespace ui
#endif

View File

@ -17,7 +17,6 @@
#include "ui/overlay.h" #include "ui/overlay.h"
#include "ui/overlay_manager.h" #include "ui/overlay_manager.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "ui/region.h"
#include "ui/theme.h" #include "ui/theme.h"
#include "ui/widget.h" #include "ui/widget.h"
@ -33,7 +32,6 @@ namespace ui {
/* Global output bitmap. */ /* Global output bitmap. */
BITMAP* ji_screen = NULL; BITMAP* ji_screen = NULL;
JRegion ji_dirty_region = NULL;
int ji_screen_w = 0; int ji_screen_w = 0;
int ji_screen_h = 0; int ji_screen_h = 0;

View File

@ -13,6 +13,10 @@
struct BITMAP; struct BITMAP;
struct FONT; struct FONT;
namespace gfx {
class Region;
}
namespace ui { namespace ui {
class ButtonBase; class ButtonBase;
@ -37,9 +41,9 @@ namespace ui {
void regenerate(); void regenerate();
virtual Cursor* getCursor(CursorType type) = 0; virtual Cursor* getCursor(CursorType type) = 0;
virtual void init_widget(Widget* widget) = 0; virtual void initWidget(Widget* widget) = 0;
virtual ui::JRegion get_window_mask(ui::Widget* widget) = 0; virtual void getWindowMask(ui::Widget* widget, gfx::Region& region) = 0;
virtual void map_decorative_widget(ui::Widget* widget) = 0; virtual void mapDecorativeWidget(ui::Widget* widget) = 0;
virtual void paintDesktop(PaintEvent& ev) = 0; virtual void paintDesktop(PaintEvent& ev) = 0;
virtual void paintBox(PaintEvent& ev) = 0; virtual void paintBox(PaintEvent& ev) = 0;

View File

@ -153,7 +153,6 @@ TipWindow::TipWindow(const char *text, bool close_on_buttonpressed)
: Window(false, text) : Window(false, text)
{ {
m_close_on_buttonpressed = close_on_buttonpressed; m_close_on_buttonpressed = close_on_buttonpressed;
m_hot_region = NULL;
m_filtering = false; m_filtering = false;
m_arrowAlign = 0; m_arrowAlign = 0;
@ -175,29 +174,18 @@ TipWindow::~TipWindow()
getManager()->removeMessageFilter(JM_BUTTONPRESSED, this); getManager()->removeMessageFilter(JM_BUTTONPRESSED, this);
getManager()->removeMessageFilter(JM_KEYPRESSED, this); getManager()->removeMessageFilter(JM_KEYPRESSED, this);
} }
if (m_hot_region != NULL) {
jregion_free(m_hot_region);
}
} }
/** void TipWindow::setHotRegion(const Region& region)
* @param region The new hot-region. This pointer is holded by the @a widget.
* So you can't destroy it after calling this routine.
*/
void TipWindow::set_hotregion(JRegion region)
{ {
ASSERT(region != NULL);
if (m_hot_region != NULL)
jregion_free(m_hot_region);
if (!m_filtering) { if (!m_filtering) {
m_filtering = true; m_filtering = true;
getManager()->addMessageFilter(JM_MOTION, this); getManager()->addMessageFilter(JM_MOTION, this);
getManager()->addMessageFilter(JM_BUTTONPRESSED, this); getManager()->addMessageFilter(JM_BUTTONPRESSED, this);
getManager()->addMessageFilter(JM_KEYPRESSED, this); getManager()->addMessageFilter(JM_KEYPRESSED, this);
} }
m_hot_region = region;
m_hotRegion = region;
} }
int TipWindow::getArrowAlign() const int TipWindow::getArrowAlign() const
@ -224,8 +212,8 @@ bool TipWindow::onProcessMessage(Message* msg)
break; break;
case JM_MOUSELEAVE: case JM_MOUSELEAVE:
if (m_hot_region == NULL) if (m_hotRegion.isEmpty())
this->closeWindow(NULL); closeWindow(NULL);
break; break;
case JM_KEYPRESSED: case JM_KEYPRESSED:
@ -250,14 +238,11 @@ bool TipWindow::onProcessMessage(Message* msg)
break; break;
case JM_MOTION: case JM_MOTION:
if (m_hot_region != NULL && if (!m_hotRegion.isEmpty() &&
getManager()->getCapture() == NULL) { getManager()->getCapture() == NULL) {
struct jrect box; // If the mouse is outside the hot-region we have to close the window
if (!m_hotRegion.contains(Point(msg->mouse.x, msg->mouse.y))) {
/* if the mouse is outside the hot-region we have to close the window */ closeWindow(NULL);
if (!jregion_point_in(m_hot_region,
msg->mouse.x, msg->mouse.y, &box)) {
this->closeWindow(NULL);
} }
} }
break; break;

View File

@ -57,7 +57,7 @@ namespace ui {
TipWindow(const char *text, bool close_on_buttonpressed = false); TipWindow(const char *text, bool close_on_buttonpressed = false);
~TipWindow(); ~TipWindow();
void set_hotregion(JRegion region); void setHotRegion(const gfx::Region& region);
int getArrowAlign() const; int getArrowAlign() const;
void setArrowAlign(int arrowAlign); void setArrowAlign(int arrowAlign);
@ -70,7 +70,7 @@ namespace ui {
private: private:
bool m_close_on_buttonpressed; bool m_close_on_buttonpressed;
JRegion m_hot_region; gfx::Region m_hotRegion;
bool m_filtering; bool m_filtering;
int m_arrowAlign; int m_arrowAlign;
}; };

View File

@ -11,7 +11,6 @@
#include "ui/message.h" #include "ui/message.h"
#include "ui/preferred_size_event.h" #include "ui/preferred_size_event.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "ui/region.h"
#include "ui/system.h" #include "ui/system.h"
#include "ui/theme.h" #include "ui/theme.h"
#include "ui/view.h" #include "ui/view.h"
@ -250,9 +249,9 @@ bool View::onProcessMessage(Message* msg)
// TODO This is theme specific stuff // TODO This is theme specific stuff
// Redraw the borders each time the focus enters or leaves the view. // Redraw the borders each time the focus enters or leaves the view.
{ {
JRegion region = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); Region region;
getDrawableRegion(region, kCutTopWindows);
invalidateRegion(region); invalidateRegion(region);
jregion_free(region);
} }
break; break;
} }

View File

@ -63,8 +63,6 @@ Widget::Widget(int type)
this->m_font = this->m_theme ? this->m_theme->default_font: NULL; this->m_font = this->m_theme ? this->m_theme->default_font: NULL;
this->m_bgColor = ui::ColorNone; this->m_bgColor = ui::ColorNone;
this->m_update_region = jregion_new(NULL, 0);
this->theme_data[0] = NULL; this->theme_data[0] = NULL;
this->theme_data[1] = NULL; this->theme_data[1] = NULL;
this->theme_data[2] = NULL; this->theme_data[2] = NULL;
@ -98,10 +96,6 @@ Widget::~Widget()
while (!m_children.empty()) while (!m_children.empty())
delete m_children.front(); delete m_children.front();
/* destroy the update region */
if (m_update_region)
jregion_free(m_update_region);
/* destroy widget position */ /* destroy widget position */
if (this->rc) if (this->rc)
jrect_free(this->rc); jrect_free(this->rc);
@ -576,6 +570,14 @@ Rect Widget::getClientBounds() const
return Rect(0, 0, jrect_w(rc), jrect_h(rc)); return Rect(0, 0, jrect_w(rc), jrect_h(rc));
} }
Rect Widget::getChildrenBounds() const
{
return Rect(rc->x1+border_width.l,
rc->y1+border_width.t,
jrect_w(rc) - border_width.l - border_width.r,
jrect_h(rc) - border_width.t - border_width.b);
}
void Widget::setBounds(const Rect& rc) void Widget::setBounds(const Rect& rc)
{ {
jrect jrc = { rc.x, rc.y, rc.x+rc.w, rc.y+rc.h }; jrect jrc = { rc.x, rc.y, rc.x+rc.w, rc.y+rc.h };
@ -595,6 +597,108 @@ void Widget::setBorder(const Border& br)
border_width.b = br.bottom(); border_width.b = br.bottom();
} }
void Widget::getRegion(gfx::Region& region)
{
if (this->type == JI_WINDOW)
getTheme()->getWindowMask(this, region);
else
region = getBounds();
}
void Widget::getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags)
{
Widget* window, *manager, *view;
getRegion(region);
// Cut the top windows areas
if (flags & kCutTopWindows) {
window = getRoot();
manager = window ? window->getManager(): NULL;
while (manager) {
const WidgetsList& windows_list = manager->getChildren();
WidgetsList::const_reverse_iterator it =
std::find(windows_list.rbegin(), windows_list.rend(), window);
if (!windows_list.empty() &&
window != windows_list.front() &&
it != windows_list.rend()) {
// Subtract the rectangles
for (++it; it != windows_list.rend(); ++it) {
Region reg1;
(*it)->getRegion(reg1);
region.createSubtraction(region, reg1);
}
}
window = manager->getRoot();
manager = window ? window->getManager(): NULL;
}
}
// Clip the areas where are children
if (!(flags & kUseChildArea) && !getChildren().empty()) {
Region reg1;
Region reg2(getChildrenBounds());
UI_FOREACH_WIDGET(getChildren(), it) {
Widget* child = *it;
if (child->isVisible()) {
Region reg3;
child->getRegion(reg3);
if (child->flags & JI_DECORATIVE) {
reg1 = getBounds();
reg1.createIntersection(reg1, reg3);
}
else {
reg1.createIntersection(reg2, reg3);
}
region.createSubtraction(region, reg1);
}
}
}
// Intersect with the parent area
if (!(this->flags & JI_DECORATIVE)) {
Widget* parent = getParent();
while (parent) {
region.createIntersection(region,
Region(parent->getChildrenBounds()));
parent = parent->getParent();
}
}
else {
Widget* parent = getParent();
if (parent) {
region.createIntersection(region,
Region(parent->getBounds()));
}
}
// Limit to the manager area
window = getRoot();
manager = (window ? window->getManager(): NULL);
while (manager) {
view = View::getView(manager);
Rect cpos;
if (view) {
cpos = static_cast<View*>(view)->getViewportBounds();
}
else
cpos = manager->getChildrenBounds();
region.createIntersection(region, Region(cpos));
window = manager->getRoot();
manager = (window ? window->getManager(): NULL);
}
}
/* gets the position of the widget */ /* gets the position of the widget */
JRect jwidget_get_rect(Widget* widget) JRect jwidget_get_rect(Widget* widget)
{ {
@ -614,141 +718,6 @@ JRect jwidget_get_child_rect(Widget* widget)
widget->rc->y2 - widget->border_width.b); widget->rc->y2 - widget->border_width.b);
} }
JRegion jwidget_get_region(Widget* widget)
{
JRegion region;
ASSERT_VALID_WIDGET(widget);
if (widget->type == JI_WINDOW)
region = widget->getTheme()->get_window_mask(widget);
else
region = jregion_new(widget->rc, 1);
return region;
}
/* gets the region to be able to draw in */
JRegion jwidget_get_drawable_region(Widget* widget, int flags)
{
Widget* window, *manager, *view;
JRegion region, reg1, reg2, reg3;
JRect cpos;
ASSERT_VALID_WIDGET(widget);
region = jwidget_get_region(widget);
// Cut the top windows areas
if (flags & JI_GDR_CUTTOPWINDOWS) {
window = widget->getRoot();
manager = window ? window->getManager(): NULL;
while (manager) {
const WidgetsList& windows_list = manager->getChildren();
WidgetsList::const_reverse_iterator it =
std::find(windows_list.rbegin(), windows_list.rend(), window);
if (!windows_list.empty() &&
window != windows_list.front() &&
it != windows_list.rend()) {
// Subtract the rectangles
for (++it; it != windows_list.rend(); ++it) {
reg1 = jwidget_get_region(*it);
jregion_subtract(region, region, reg1);
jregion_free(reg1);
}
}
window = manager->getRoot();
manager = window ? window->getManager(): NULL;
}
}
// Clip the areas where are children
if (!(flags & JI_GDR_USECHILDAREA) && !widget->getChildren().empty()) {
cpos = jwidget_get_child_rect(widget);
reg1 = jregion_new(NULL, 0);
reg2 = jregion_new(cpos, 1);
UI_FOREACH_WIDGET(widget->getChildren(), it) {
Widget* child = *it;
if (child->isVisible()) {
reg3 = jwidget_get_region(child);
if (child->flags & JI_DECORATIVE) {
jregion_reset(reg1, widget->rc);
jregion_intersect(reg1, reg1, reg3);
}
else {
jregion_intersect(reg1, reg2, reg3);
}
jregion_subtract(region, region, reg1);
jregion_free(reg3);
}
}
jregion_free(reg1);
jregion_free(reg2);
jrect_free(cpos);
}
// Intersect with the parent area
if (!(widget->flags & JI_DECORATIVE)) {
Widget* parent = widget->getParent();
reg1 = jregion_new(NULL, 0);
while (parent) {
cpos = jwidget_get_child_rect(parent);
jregion_reset(reg1, cpos);
jregion_intersect(region, region, reg1);
jrect_free(cpos);
parent = parent->getParent();
}
jregion_free(reg1);
}
else {
Widget* parent = widget->getParent();
if (parent) {
cpos = jwidget_get_rect(parent);
reg1 = jregion_new(cpos, 1);
jregion_intersect(region, region, reg1);
jregion_free(reg1);
jrect_free(cpos);
}
}
// Limit to the manager area
window = widget->getRoot();
manager = window ? window->getManager(): NULL;
while (manager) {
view = View::getView(manager);
if (view) {
Rect vp = static_cast<View*>(view)->getViewportBounds();
cpos = jrect_new(vp.x, vp.y, vp.x+vp.w, vp.y+vp.h);
}
else
cpos = jwidget_get_child_rect(manager);
/* if (!manager->parent) */
/* cpos = jwidget_get_rect(manager); */
/* else */
/* cpos = jwidget_get_child_rect(manager->parent); */
reg1 = jregion_new(cpos, 1);
jregion_intersect(region, region, reg1);
jregion_free(reg1);
jrect_free(cpos);
window = manager->getRoot();
manager = window ? window->getManager(): NULL;
}
/* return the region */
return region;
}
int jwidget_get_text_length(const Widget* widget) int jwidget_get_text_length(const Widget* widget)
{ {
#if 1 #if 1
@ -934,9 +903,7 @@ void jwidget_set_max_size(Widget* widget, int w, int h)
void Widget::flushRedraw() void Widget::flushRedraw()
{ {
std::queue<Widget*> processing; std::queue<Widget*> processing;
int c, nrects;
Message* msg; Message* msg;
JRect rc;
if (this->flags & JI_DIRTY) { if (this->flags & JI_DIRTY) {
this->flags ^= JI_DIRTY; this->flags ^= JI_DIRTY;
@ -961,31 +928,35 @@ void Widget::flushRedraw()
} }
} }
nrects = JI_REGION_NUM_RECTS(widget->m_update_region); if (!widget->m_updateRegion.isEmpty()) {
if (nrects > 0) { // Intersect m_updateRegion with drawable area.
/* get areas to draw */ {
JRegion region = jwidget_get_drawable_region(widget, JI_GDR_CUTTOPWINDOWS); Region region;
jregion_intersect(widget->m_update_region, widget->getDrawableRegion(region, kCutTopWindows);
widget->m_update_region, region); widget->m_updateRegion.createIntersection(widget->m_updateRegion, region);
jregion_free(region); }
nrects = JI_REGION_NUM_RECTS(widget->m_update_region); size_t c, nrects = widget->m_updateRegion.size();
Region::const_iterator it = widget->m_updateRegion.begin();
/* draw the widget */ // Draw the widget
for (c=0, rc=JI_REGION_RECTS(widget->m_update_region); for (c=0; c<nrects; c++, ++it) {
c<nrects; const Rect& rc = *it;
c++, rc++) {
/* create the draw message */ // Create the draw message
msg = jmessage_new(JM_DRAW); msg = jmessage_new(JM_DRAW);
msg->draw.count = nrects-1 - c; msg->draw.count = nrects-1 - c;
msg->draw.rect = *rc; msg->draw.rect.x1 = rc.x;
msg->draw.rect.y1 = rc.y;
msg->draw.rect.x2 = rc.x2();
msg->draw.rect.y2 = rc.y2();
jmessage_add_dest(msg, widget); jmessage_add_dest(msg, widget);
/* enqueue the draw message */ // Enqueue the draw message
getManager()->enqueueMessage(msg); getManager()->enqueueMessage(msg);
} }
jregion_empty(widget->m_update_region); widget->m_updateRegion.clear();
} }
} }
} }
@ -1003,10 +974,8 @@ void Widget::setDoubleBuffered(bool doubleBuffered)
void Widget::invalidate() void Widget::invalidate()
{ {
if (isVisible()) { if (isVisible()) {
JRegion reg1 = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); m_updateRegion.clear();
getDrawableRegion(m_updateRegion, kCutTopWindows);
jregion_copy(this->m_update_region, reg1);
jregion_free(reg1);
mark_dirty_flag(this); mark_dirty_flag(this);
@ -1017,53 +986,37 @@ void Widget::invalidate()
void Widget::invalidateRect(const gfx::Rect& rect) void Widget::invalidateRect(const gfx::Rect& rect)
{ {
if (isVisible()) { if (isVisible())
JRect tmp = jrect_new(rect.x, rect.y, rect.x+rect.w, rect.y+rect.h); invalidateRegion(Region(rect));
invalidateRect(tmp);
jrect_free(tmp);
}
} }
void Widget::invalidateRect(const JRect rect) void Widget::invalidateRegion(const Region& region)
{
if (isVisible()) {
JRegion reg1 = jregion_new(rect, 1);
invalidateRegion(reg1);
jregion_free(reg1);
}
}
void Widget::invalidateRegion(const JRegion region)
{ {
onInvalidateRegion(region); onInvalidateRegion(region);
} }
void Widget::scrollRegion(JRegion region, int dx, int dy) void Widget::scrollRegion(const Region& region, int dx, int dy)
{ {
if (dx != 0 || dy != 0) { if (dx != 0 || dy != 0) {
JRegion reg2 = jregion_new(NULL, 0); Region reg2 = region;
reg2.offset(dx, dy);
jregion_copy(reg2, region); reg2.createIntersection(reg2, region);
jregion_translate(reg2, dx, dy); reg2.offset(-dx, -dy);
jregion_intersect(reg2, reg2, region);
jregion_translate(reg2, -dx, -dy);
// Move screen pixels
jmouse_hide(); jmouse_hide();
ji_move_region(reg2, dx, dy); ji_move_region(reg2, dx, dy);
jmouse_show(); jmouse_show();
jregion_translate(reg2, dx, dy); reg2.offset(dx, dy);
jregion_union(this->m_update_region, this->m_update_region, region); m_updateRegion.createUnion(m_updateRegion, region);
jregion_subtract(this->m_update_region, this->m_update_region, reg2); m_updateRegion.createSubtraction(m_updateRegion, reg2);
mark_dirty_flag(this); mark_dirty_flag(this);
// Generate the JM_DRAW messages for the widget's m_update_region // Generate the JM_DRAW messages for the widget's m_updateRegion
this->flushRedraw(); flushRedraw();
jregion_free(reg2);
} }
} }
@ -1362,31 +1315,28 @@ bool Widget::onProcessMessage(Message* msg)
// EVENTS // EVENTS
// =============================================================== // ===============================================================
void Widget::onInvalidateRegion(const JRegion region) void Widget::onInvalidateRegion(const Region& region)
{ {
if (isVisible() && if (isVisible() && region.contains(getBounds()) != Region::Out) {
jregion_rect_in(region, this->rc) != JI_RGNOUT) { Region reg1;
JRegion reg1 = jregion_new(NULL, 0); reg1.createUnion(m_updateRegion, region);
JRegion reg2 = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); {
Region reg2;
jregion_union(reg1, this->m_update_region, region); getDrawableRegion(reg2, kCutTopWindows);
jregion_intersect(this->m_update_region, reg1, reg2); m_updateRegion.createIntersection(reg1, reg2);
jregion_free(reg2); }
reg1.createSubtraction(region, m_updateRegion);
jregion_subtract(reg1, region, this->m_update_region);
mark_dirty_flag(this); mark_dirty_flag(this);
UI_FOREACH_WIDGET(getChildren(), it) UI_FOREACH_WIDGET(getChildren(), it)
(*it)->invalidateRegion(reg1); (*it)->invalidateRegion(reg1);
jregion_free(reg1);
} }
} }
void Widget::onPreferredSize(PreferredSizeEvent& ev) void Widget::onPreferredSize(PreferredSizeEvent& ev)
{ {
ev.setPreferredSize(Size(this->min_w, this->min_h)); ev.setPreferredSize(Size(min_w, min_h));
} }
void Widget::onLoadLayout(LoadLayoutEvent& ev) void Widget::onLoadLayout(LoadLayoutEvent& ev)
@ -1412,7 +1362,7 @@ void Widget::onBroadcastMouseMessage(WidgetsList& targets)
void Widget::onInitTheme(InitThemeEvent& ev) void Widget::onInitTheme(InitThemeEvent& ev)
{ {
if (m_theme) { if (m_theme) {
m_theme->init_widget(this); m_theme->initWidget(this);
if (!(flags & JI_INITIALIZED)) if (!(flags & JI_INITIALIZED))
flags |= JI_INITIALIZED; flags |= JI_INITIALIZED;

View File

@ -11,6 +11,7 @@
#include "gfx/border.h" #include "gfx/border.h"
#include "gfx/rect.h" #include "gfx/rect.h"
#include "gfx/region.h"
#include "gfx/size.h" #include "gfx/size.h"
#include "ui/base.h" #include "ui/base.h"
#include "ui/color.h" #include "ui/color.h"
@ -42,8 +43,6 @@ namespace ui {
JRect jwidget_get_rect(Widget* widget); JRect jwidget_get_rect(Widget* widget);
JRect jwidget_get_child_rect(Widget* widget); JRect jwidget_get_child_rect(Widget* widget);
JRegion jwidget_get_region(Widget* widget);
JRegion jwidget_get_drawable_region(Widget* widget, int flags);
int jwidget_get_text_length(const Widget* widget); int jwidget_get_text_length(const Widget* widget);
int jwidget_get_text_height(const Widget* widget); int jwidget_get_text_height(const Widget* widget);
void jwidget_get_texticon_info(Widget* widget, void jwidget_get_texticon_info(Widget* widget,
@ -242,11 +241,21 @@ namespace ui {
gfx::Rect getBounds() const; gfx::Rect getBounds() const;
gfx::Rect getClientBounds() const; gfx::Rect getClientBounds() const;
gfx::Rect getChildrenBounds() const;
void setBounds(const gfx::Rect& rc); void setBounds(const gfx::Rect& rc);
gfx::Border getBorder() const; gfx::Border getBorder() const;
void setBorder(const gfx::Border& border); void setBorder(const gfx::Border& border);
// Flags for getDrawableRegion()
enum DrawableRegionFlags {
kCutTopWindows = 1, // Cut areas where are windows on top.
kUseChildArea = 2, // Use areas where are children.
};
void getRegion(gfx::Region& region);
void getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags);
// =============================================================== // ===============================================================
// REFRESH ISSUES // REFRESH ISSUES
// =============================================================== // ===============================================================
@ -256,12 +265,11 @@ namespace ui {
void invalidate(); void invalidate();
void invalidateRect(const gfx::Rect& rect); void invalidateRect(const gfx::Rect& rect);
void invalidateRect(const JRect rect); void invalidateRegion(const gfx::Region& region);
void invalidateRegion(const JRegion region);
void flushRedraw(); void flushRedraw();
void scrollRegion(JRegion region, int dx, int dy); void scrollRegion(const gfx::Region& region, int dx, int dy);
// =============================================================== // ===============================================================
// GUI MANAGER // GUI MANAGER
@ -312,7 +320,7 @@ namespace ui {
// EVENTS // EVENTS
// =============================================================== // ===============================================================
virtual void onInvalidateRegion(const JRegion region); virtual void onInvalidateRegion(const gfx::Region& region);
virtual void onPreferredSize(PreferredSizeEvent& ev); virtual void onPreferredSize(PreferredSizeEvent& ev);
virtual void onLoadLayout(LoadLayoutEvent& ev); virtual void onLoadLayout(LoadLayoutEvent& ev);
virtual void onSaveLayout(SaveLayoutEvent& ev); virtual void onSaveLayout(SaveLayoutEvent& ev);
@ -332,7 +340,7 @@ namespace ui {
std::string m_text; // Widget text std::string m_text; // Widget text
struct FONT *m_font; // Text font type struct FONT *m_font; // Text font type
ui::Color m_bgColor; // Background color ui::Color m_bgColor; // Background color
JRegion m_update_region; // Region to be redrawed. gfx::Region m_updateRegion;; // Region to be redrawed.
WidgetsList m_children; // Sub-widgets WidgetsList m_children; // Sub-widgets
Widget* m_parent; // Who is the parent? Widget* m_parent; // Who is the parent?
gfx::Size* m_preferredSize; gfx::Size* m_preferredSize;

View File

@ -460,10 +460,8 @@ void Window::onPreferredSize(PreferredSizeEvent& ev)
Widget* manager = getManager(); Widget* manager = getManager();
if (m_is_desktop) { if (m_is_desktop) {
JRect cpos = jwidget_get_child_rect(manager); Rect cpos = manager->getChildrenBounds();
ev.setPreferredSize(jrect_w(cpos), ev.setPreferredSize(cpos.w, cpos.h);
jrect_h(cpos));
jrect_free(cpos);
} }
else { else {
Size maxSize(0, 0); Size maxSize(0, 0);
@ -515,21 +513,19 @@ void Window::onSetText()
void Window::window_set_position(JRect rect) void Window::window_set_position(JRect rect)
{ {
/* copy the new position rectangle */ // Copy the new position rectangle
jrect_copy(this->rc, rect); jrect_copy(this->rc, rect);
JRect cpos = jwidget_get_child_rect(this); Rect cpos = getChildrenBounds();
/* set all the children to the same "child_pos" */ /* set all the children to the same "child_pos" */
UI_FOREACH_WIDGET(getChildren(), it) { UI_FOREACH_WIDGET(getChildren(), it) {
Widget* child = *it; Widget* child = *it;
if (child->isDecorative()) if (child->isDecorative())
child->getTheme()->map_decorative_widget(child); child->getTheme()->mapDecorativeWidget(child);
else else
jwidget_set_rect(child, cpos); child->setBounds(cpos);
} }
jrect_free(cpos);
} }
void Window::limit_size(int *w, int *h) void Window::limit_size(int *w, int *h)
@ -540,13 +536,13 @@ void Window::limit_size(int *w, int *h)
void Window::move_window(JRect rect, bool use_blit) void Window::move_window(JRect rect, bool use_blit)
{ {
#define FLAGS JI_GDR_CUTTOPWINDOWS | JI_GDR_USECHILDAREA #define FLAGS (DrawableRegionFlags)(kCutTopWindows | kUseChildArea)
Manager* manager = getManager(); Manager* manager = getManager();
JRegion old_drawable_region; Region old_drawable_region;
JRegion new_drawable_region; Region new_drawable_region;
JRegion manager_refresh_region; Region manager_refresh_region; // A region to refresh the manager later
JRegion window_refresh_region; Region window_refresh_region; // A new region to refresh the window later
JRect old_pos; JRect old_pos;
JRect man_pos; JRect man_pos;
Message* msg; Message* msg;
@ -564,70 +560,59 @@ void Window::move_window(JRect rect, bool use_blit)
jmessage_add_dest(msg, this); jmessage_add_dest(msg, this);
manager->enqueueMessage(msg); manager->enqueueMessage(msg);
/* get the region & the drawable region of the window */ // Get the region & the drawable region of the window
old_drawable_region = jwidget_get_drawable_region(this, FLAGS); getDrawableRegion(old_drawable_region, FLAGS);
/* if the size of the window changes... */ // If the size of the window changes...
if (jrect_w(old_pos) != jrect_w(rect) || if (jrect_w(old_pos) != jrect_w(rect) ||
jrect_h(old_pos) != jrect_h(rect)) { jrect_h(old_pos) != jrect_h(rect)) {
/* we have to change the whole positions sending JM_SETPOS // We have to change the whole positions sending JM_SETPOS
messages... */ // messages...
window_set_position(rect); window_set_position(rect);
} }
else { else {
/* we can just displace all the widgets // We can just displace all the widgets by a delta (new_position -
by a delta (new_position - old_position)... */ // old_position)...
displace_widgets(this, displace_widgets(this,
rect->x1 - old_pos->x1, rect->x1 - old_pos->x1,
rect->y1 - old_pos->y1); rect->y1 - old_pos->y1);
} }
/* get the new drawable region of the window (it's new because we // Get the new drawable region of the window (it's new because we
moved the window to "rect") */ // moved the window to "rect")
new_drawable_region = jwidget_get_drawable_region(this, FLAGS); getDrawableRegion(new_drawable_region, FLAGS);
/* create a new region to refresh the manager later */ // First of all, we have to refresh the manager in the old window's
manager_refresh_region = jregion_new(NULL, 0); // drawable region, but we have to substract the new window's
// drawable region.
/* create a new region to refresh the window later */ manager_refresh_region.createSubtraction(old_drawable_region,
window_refresh_region = jregion_new(NULL, 0);
/* first of all, we have to refresh the manager in the old window's
drawable region... */
jregion_copy(manager_refresh_region, old_drawable_region);
/* ...but we have to substract the new window's drawable region (and
that is all for the manager's refresh region) */
jregion_subtract(manager_refresh_region, manager_refresh_region,
new_drawable_region); new_drawable_region);
/* now we have to setup the window's refresh region... */ // In second place, we have to setup the window's refresh region...
/* if "use_blit" isn't activated, we have to redraw the whole window // If "use_blit" isn't activated, we have to redraw the whole window
(sending JM_DRAW messages) in the new drawable region */ // (sending JM_DRAW messages) in the new drawable region
if (!use_blit) { if (!use_blit) {
jregion_copy(window_refresh_region, new_drawable_region); window_refresh_region = new_drawable_region;
} }
/* if "use_blit" is activated, we can move the old drawable to the // If "use_blit" is activated, we can move the old drawable to the
new position (to redraw as little as possible) */ // new position (to redraw as little as possible)
else { else {
JRegion reg1 = jregion_new(NULL, 0); Region reg1;
JRegion moveable_region = jregion_new(NULL, 0); Region moveable_region;
/* add a region to draw areas which were outside of the screen */ // Add a region to draw areas which were outside of the screen
jregion_copy(reg1, new_drawable_region); reg1 = new_drawable_region;
jregion_translate(reg1, reg1.offset(old_pos->x1 - this->rc->x1,
old_pos->x1 - this->rc->x1,
old_pos->y1 - this->rc->y1); old_pos->y1 - this->rc->y1);
jregion_intersect(moveable_region, old_drawable_region, reg1); moveable_region.createIntersection(old_drawable_region, reg1);
jregion_subtract(reg1, reg1, moveable_region); reg1.createSubtraction(reg1, moveable_region);
jregion_translate(reg1, reg1.offset(this->rc->x1 - old_pos->x1,
this->rc->x1 - old_pos->x1,
this->rc->y1 - old_pos->y1); this->rc->y1 - old_pos->y1);
jregion_union(window_refresh_region, window_refresh_region, reg1); window_refresh_region.createUnion(window_refresh_region, reg1);
/* move the window's graphics */ // Move the window's graphics
jmouse_hide(); jmouse_hide();
set_clip_rect(ji_screen, set_clip_rect(ji_screen,
man_pos->x1, man_pos->y1, man_pos->x2-1, man_pos->y2-1); man_pos->x1, man_pos->y1, man_pos->x2-1, man_pos->y2-1);
@ -637,18 +622,11 @@ void Window::move_window(JRect rect, bool use_blit)
this->rc->y1 - old_pos->y1); this->rc->y1 - old_pos->y1);
set_clip_rect(ji_screen, 0, 0, JI_SCREEN_W-1, JI_SCREEN_H-1); set_clip_rect(ji_screen, 0, 0, JI_SCREEN_W-1, JI_SCREEN_H-1);
jmouse_show(); jmouse_show();
jregion_free(reg1);
jregion_free(moveable_region);
} }
manager->invalidateDisplayRegion(manager_refresh_region); manager->invalidateDisplayRegion(manager_refresh_region);
invalidateRegion(window_refresh_region); invalidateRegion(window_refresh_region);
jregion_free(old_drawable_region);
jregion_free(new_drawable_region);
jregion_free(manager_refresh_region);
jregion_free(window_refresh_region);
jrect_free(old_pos); jrect_free(old_pos);
jrect_free(man_pos); jrect_free(man_pos);
} }

View File

@ -254,17 +254,11 @@ void ColorButton::openSelectorDialog()
m_window->getManager()->dispatchMessages(); m_window->getManager()->dispatchMessages();
m_window->layout(); m_window->layout();
/* setup the hot-region */ // Setup the hot-region
{ gfx::Rect rc = getBounds().createUnion(m_window->getBounds());
JRect rc = jrect_new(MIN(this->rc->x1, m_window->rc->x1)-8, rc.enlarge(8);
MIN(this->rc->y1, m_window->rc->y1)-8, gfx::Region rgn(rc);
MAX(this->rc->x2, m_window->rc->x2)+8,
MAX(this->rc->y2, m_window->rc->y2)+8);
JRegion rgn = jregion_new(rc, 1);
jrect_free(rc);
static_cast<PopupWindow*>(m_window)->setHotRegion(rgn); static_cast<PopupWindow*>(m_window)->setHotRegion(rgn);
}
} }
void ColorButton::closeSelectorDialog() void ColorButton::closeSelectorDialog()

View File

@ -32,7 +32,6 @@
#include "tools/tool.h" #include "tools/tool.h"
#include "ui/base.h" #include "ui/base.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "ui/region.h"
#include "ui/system.h" #include "ui/system.h"
#include "ui/widget.h" #include "ui/widget.h"
#include "ui_context.h" #include "ui_context.h"
@ -85,8 +84,8 @@ static int saved_pixel_n;
// These clipping regions are shared between all editors, so we cannot // These clipping regions are shared between all editors, so we cannot
// make assumptions about their old state // make assumptions about their old state
static JRegion clipping_region = NULL; static gfx::Region clipping_region;
static JRegion old_clipping_region = NULL; static gfx::Region old_clipping_region;
static void generate_cursor_boundaries(); static void generate_cursor_boundaries();
@ -98,8 +97,6 @@ static void savepixel(BITMAP *bmp, int x, int y, int color);
static void drawpixel(BITMAP *bmp, int x, int y, int color); static void drawpixel(BITMAP *bmp, int x, int y, int color);
static void cleanpixel(BITMAP *bmp, int x, int y, int color); static void cleanpixel(BITMAP *bmp, int x, int y, int color);
static int point_inside_region(int x, int y, JRegion region);
static int get_pen_color(Sprite *sprite); static int get_pen_color(Sprite *sprite);
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -240,8 +237,8 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
ASSERT(m_cursor_thick == 0); ASSERT(m_cursor_thick == 0);
ASSERT(m_sprite != NULL); ASSERT(m_sprite != NULL);
/* get drawable region */ // Get drawable region
clipping_region = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); getDrawableRegion(clipping_region, kCutTopWindows);
/* get cursor color */ /* get cursor color */
cursor_negative = is_cursor_mask(); cursor_negative = is_cursor_mask();
@ -335,9 +332,7 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
m_cursor_editor_x = x; m_cursor_editor_x = x;
m_cursor_editor_y = y; m_cursor_editor_y = y;
/* save the clipping-region to know where to clean the pixels */ // Save the clipping-region to know where to clean the pixels
if (old_clipping_region)
jregion_free(old_clipping_region);
old_clipping_region = clipping_region; old_clipping_region = clipping_region;
} }
@ -404,7 +399,7 @@ void Editor::editor_clean_cursor(bool refresh)
ASSERT(m_cursor_thick != 0); ASSERT(m_cursor_thick != 0);
ASSERT(m_sprite != NULL); ASSERT(m_sprite != NULL);
clipping_region = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); getDrawableRegion(clipping_region, kCutTopWindows);
x = m_cursor_editor_x; x = m_cursor_editor_x;
y = m_cursor_editor_y; y = m_cursor_editor_y;
@ -438,12 +433,8 @@ void Editor::editor_clean_cursor(bool refresh)
m_cursor_thick = 0; m_cursor_thick = 0;
jregion_free(clipping_region); clipping_region.clear();
if (old_clipping_region) old_clipping_region.clear();
jregion_free(old_clipping_region);
clipping_region = NULL;
old_clipping_region = NULL;
} }
/** /**
@ -634,13 +625,13 @@ static void editor_cursor_bounds(Editor *editor, int x, int y, int color, void (
static void savepixel(BITMAP *bmp, int x, int y, int color) static void savepixel(BITMAP *bmp, int x, int y, int color)
{ {
if (saved_pixel_n < MAX_SAVED && point_inside_region(x, y, clipping_region)) if (saved_pixel_n < MAX_SAVED && clipping_region.contains(gfx::Point(x, y)))
saved_pixel[saved_pixel_n++] = getpixel(bmp, x, y); saved_pixel[saved_pixel_n++] = getpixel(bmp, x, y);
} }
static void drawpixel(BITMAP *bmp, int x, int y, int color) static void drawpixel(BITMAP *bmp, int x, int y, int color)
{ {
if (saved_pixel_n < MAX_SAVED && point_inside_region(x, y, clipping_region)) { if (saved_pixel_n < MAX_SAVED && clipping_region.contains(gfx::Point(x, y))) {
if (cursor_negative) { if (cursor_negative) {
int r, g, b, c = saved_pixel[saved_pixel_n++]; int r, g, b, c = saved_pixel[saved_pixel_n++];
@ -659,20 +650,14 @@ static void drawpixel(BITMAP *bmp, int x, int y, int color)
static void cleanpixel(BITMAP *bmp, int x, int y, int color) static void cleanpixel(BITMAP *bmp, int x, int y, int color)
{ {
if (saved_pixel_n < MAX_SAVED) { if (saved_pixel_n < MAX_SAVED) {
if (point_inside_region(x, y, clipping_region)) if (clipping_region.contains(gfx::Point(x, y)))
putpixel(bmp, x, y, saved_pixel[saved_pixel_n++]); putpixel(bmp, x, y, saved_pixel[saved_pixel_n++]);
else if (old_clipping_region && else if (!old_clipping_region.isEmpty() &&
point_inside_region(x, y, old_clipping_region)) old_clipping_region.contains(gfx::Point(x, y)))
saved_pixel_n++; saved_pixel_n++;
} }
} }
static int point_inside_region(int x, int y, JRegion region)
{
struct jrect box;
return jregion_point_in(region, x, y, &box);
}
static int get_pen_color(Sprite *sprite) static int get_pen_color(Sprite *sprite)
{ {
app::Color c = UIContext::instance()->getSettings()->getFgColor(); app::Color c = UIContext::instance()->getSettings()->getFgColor();

View File

@ -300,14 +300,14 @@ void Editor::setEditorScroll(int x, int y, int use_refresh_region)
{ {
View* view = View::getView(this); View* view = View::getView(this);
Point oldScroll; Point oldScroll;
JRegion region = NULL; Region region;
int thick = m_cursor_thick; int thick = m_cursor_thick;
if (thick) if (thick)
editor_clean_cursor(); editor_clean_cursor();
if (use_refresh_region) { if (use_refresh_region) {
region = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); getDrawableRegion(region, kCutTopWindows);
oldScroll = view->getViewScroll(); oldScroll = view->getViewScroll();
} }
@ -327,11 +327,9 @@ void Editor::setEditorScroll(int x, int y, int use_refresh_region)
if (use_refresh_region) { if (use_refresh_region) {
// Move screen with blits // Move screen with blits
this->scrollRegion(region, scrollRegion(region,
oldScroll.x - newScroll.x, oldScroll.x - newScroll.x,
oldScroll.y - newScroll.y); oldScroll.y - newScroll.y);
jregion_free(region);
} }
if (thick) if (thick)
@ -495,22 +493,20 @@ void Editor::drawSprite(int x1, int y1, int x2, int y2)
void Editor::drawSpriteSafe(int x1, int y1, int x2, int y2) void Editor::drawSpriteSafe(int x1, int y1, int x2, int y2)
{ {
JRegion region = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); Region region;
int c, nrects = JI_REGION_NUM_RECTS(region); getDrawableRegion(region, kCutTopWindows);
int cx1, cy1, cx2, cy2;
JRect rc;
int cx1, cy1, cx2, cy2;
get_clip_rect(ji_screen, &cx1, &cy1, &cx2, &cy2); get_clip_rect(ji_screen, &cx1, &cy1, &cx2, &cy2);
for (c=0, rc=JI_REGION_RECTS(region); for (Region::const_iterator it=region.begin(), end=region.end();
c<nrects; it != end; ++it) {
c++, rc++) { const Rect& rc = *it;
add_clip_rect(ji_screen, rc->x1, rc->y1, rc->x2-1, rc->y2-1);
add_clip_rect(ji_screen, rc.x, rc.y, rc.x2()-1, rc.y2()-1);
drawSprite(x1, y1, x2, y2); drawSprite(x1, y1, x2, y2);
set_clip_rect(ji_screen, cx1, cy1, cx2, cy2); set_clip_rect(ji_screen, cx1, cy1, cx2, cy2);
} }
jregion_free(region);
} }
/** /**
@ -582,9 +578,8 @@ void Editor::drawMaskSafe()
m_document->getBoundariesSegments()) { m_document->getBoundariesSegments()) {
int thick = m_cursor_thick; int thick = m_cursor_thick;
JRegion region = jwidget_get_drawable_region(this, JI_GDR_CUTTOPWINDOWS); Region region;
int c, nrects = JI_REGION_NUM_RECTS(region); getDrawableRegion(region, kCutTopWindows);
JRect rc;
acquire_bitmap(ji_screen); acquire_bitmap(ji_screen);
@ -593,14 +588,13 @@ void Editor::drawMaskSafe()
else else
jmouse_hide(); jmouse_hide();
for (c=0, rc=JI_REGION_RECTS(region); for (Region::const_iterator it=region.begin(), end=region.end();
c<nrects; it != end; ++it) {
c++, rc++) { const Rect& rc = *it;
set_clip_rect(ji_screen, rc->x1, rc->y1, rc->x2-1, rc->y2-1); set_clip_rect(ji_screen, rc.x, rc.y, rc.x2()-1, rc.y2()-1);
drawMask(); drawMask();
} }
set_clip_rect(ji_screen, 0, 0, JI_SCREEN_W-1, JI_SCREEN_H-1); set_clip_rect(ji_screen, 0, 0, JI_SCREEN_W-1, JI_SCREEN_H-1);
jregion_free(region);
// Draw the cursor // Draw the cursor
if (thick) if (thick)

View File

@ -53,11 +53,9 @@ void PopupWindowPin::onPinClick(Event& ev)
makeFloating(); makeFloating();
} }
else { else {
JRect rc = jrect_new(this->rc->x1-8, this->rc->y1-8, this->rc->x2+8, this->rc->y2+8); gfx::Rect rc = getBounds();
JRegion rgn = jregion_new(rc, 1); rc.enlarge(8);
jrect_free(rc); setHotRegion(gfx::Region(rc));
setHotRegion(rgn);
makeFixed(); makeFixed();
} }
} }

View File

@ -400,9 +400,7 @@ void ToolBar::openPopupWindow(int group_index, ToolGroup* tool_group)
// Redraw the overlapped area and save it to use it in the ToolStrip::onProcessMessage(JM_DRAW) // Redraw the overlapped area and save it to use it in the ToolStrip::onProcessMessage(JM_DRAW)
{ {
JRect rcTemp = jrect_new(rc.x, rc.y, rc.x+rc.w, rc.y+rc.h); getManager()->invalidateRect(rc);
getManager()->invalidateRect(rcTemp);
jrect_free(rcTemp);
// Flush JM_DRAW messages and send them // Flush JM_DRAW messages and send them
getManager()->flushRedraw(); getManager()->flushRedraw();
@ -413,11 +411,9 @@ void ToolBar::openPopupWindow(int group_index, ToolGroup* tool_group)
} }
// Set hotregion of popup window // Set hotregion of popup window
{ Region rgn(rc);
jrect rc2 = { rc.x, rc.y, this->rc->x2, rc.y+rc.h }; rgn.createUnion(rgn, Region(getBounds()));
JRegion hotregion = jregion_new(&rc2, 1); m_popupWindow->setHotRegion(rgn);
m_popupWindow->setHotRegion(hotregion);
}
m_popupWindow->set_autoremap(false); m_popupWindow->set_autoremap(false);
m_popupWindow->setBounds(rc); m_popupWindow->setBounds(rc);