diff options
| author | Felix Domke <tmbinc@elitedvb.net> | 2005-08-31 03:05:27 +0000 |
|---|---|---|
| committer | Felix Domke <tmbinc@elitedvb.net> | 2005-08-31 03:05:27 +0000 |
| commit | 87bfe5dfced0fb7a4e9839fdafa898261a39c86c (patch) | |
| tree | e9cd842941df0e2fc679931f18701fbacf071c77 /lib/gui | |
| parent | 58f644a3102613e874ecc0faf999da16c353f264 (diff) | |
| download | enigma2-87bfe5dfced0fb7a4e9839fdafa898261a39c86c.tar.gz enigma2-87bfe5dfced0fb7a4e9839fdafa898261a39c86c.zip | |
- fix serious problems in widget code. fixup buffered mode. add animation support.lib/gui
Diffstat (limited to 'lib/gui')
| -rw-r--r-- | lib/gui/Makefile.am | 6 | ||||
| -rw-r--r-- | lib/gui/ewidget.cpp | 27 | ||||
| -rw-r--r-- | lib/gui/ewidget.h | 2 | ||||
| -rw-r--r-- | lib/gui/ewidgetanimation.cpp | 46 | ||||
| -rw-r--r-- | lib/gui/ewidgetanimation.h | 25 | ||||
| -rw-r--r-- | lib/gui/ewidgetdesktop.cpp | 153 | ||||
| -rw-r--r-- | lib/gui/ewidgetdesktop.h | 14 |
7 files changed, 225 insertions, 48 deletions
diff --git a/lib/gui/Makefile.am b/lib/gui/Makefile.am index 951cc4f5..55a7e534 100644 --- a/lib/gui/Makefile.am +++ b/lib/gui/Makefile.am @@ -7,7 +7,5 @@ noinst_LIBRARIES = libenigma_gui.a libenigma_gui_a_SOURCES = \ ebutton.cpp elabel.cpp eslider.cpp ewidget.cpp ewidgetdesktop.cpp \ ewindow.cpp ewindowstyle.cpp elistbox.cpp elistboxcontent.cpp \ - epixmap.cpp ewindowstyleskinned.cpp einput.cpp einputstring.cpp einputnumber.cpp - - - + epixmap.cpp ewindowstyleskinned.cpp einput.cpp einputstring.cpp einputnumber.cpp \ + ewidgetanimation.cpp diff --git a/lib/gui/ewidget.cpp b/lib/gui/ewidget.cpp index 474e295d..8cb7d4ae 100644 --- a/lib/gui/ewidget.cpp +++ b/lib/gui/ewidget.cpp @@ -3,7 +3,7 @@ extern void dumpRegion(const gRegion ®ion); -eWidget::eWidget(eWidget *parent): m_parent(parent ? parent->child() : 0) +eWidget::eWidget(eWidget *parent): m_animation(this), m_parent(parent ? parent->child() : 0) { m_vis = 0; m_desktop = 0; @@ -13,7 +13,7 @@ eWidget::eWidget(eWidget *parent): m_parent(parent ? parent->child() : 0) if (m_parent) m_vis = wVisShow; - + if (m_parent) { m_parent->m_childs.push_back(this); @@ -26,20 +26,19 @@ eWidget::eWidget(eWidget *parent): m_parent(parent ? parent->child() : 0) void eWidget::move(ePoint pos) { - m_position = pos + m_client_offset; + pos = pos + m_client_offset; if (m_position == pos) return; + + m_position = pos; - /* we invalidate before and after the move to - cause a correct redraw. The area which is - included both before and after isn't redrawn - twice because a invalidate doesn't immediately - redraws the region. */ - invalidate(); event(evtChangedPosition); - recalcClipRegionsWhenVisible(); - invalidate(); + recalcClipRegionsWhenVisible(); + + /* try native move if supported. */ + if ((m_vis & wVisShow) && ((!m_desktop) || m_desktop->movedWidget(this))) + invalidate(); } void eWidget::resize(eSize size) @@ -110,7 +109,7 @@ void eWidget::show() abspos += root->position(); } - root->m_desktop->recalcClipRegions(); + root->m_desktop->recalcClipRegions(root); gRegion abs = m_visible_with_childs; abs.moveBy(abspos); @@ -144,7 +143,7 @@ void eWidget::hide() gRegion abs = m_visible_with_childs; abs.moveBy(abspos); - root->m_desktop->recalcClipRegions(); + root->m_desktop->recalcClipRegions(root); root->m_desktop->invalidate(abs); } @@ -228,7 +227,7 @@ void eWidget::recalcClipRegionsWhenVisible() break; if (t->m_desktop) { - t->m_desktop->recalcClipRegions(); + t->m_desktop->recalcClipRegions(t); break; } t = t->m_parent; diff --git a/lib/gui/ewidget.h b/lib/gui/ewidget.h index 8bd199f9..5cb139c5 100644 --- a/lib/gui/ewidget.h +++ b/lib/gui/ewidget.h @@ -4,6 +4,7 @@ #include <lib/gdi/grc.h> /* for gRegion */ #include <lib/base/eptrlist.h> /* for eSmartPtrList */ #include <lib/gui/ewindowstyle.h> /* for eWindowStyle */ +#include <lib/gui/ewidgetanimation.h> class eWidgetDesktop;class eWidgetDesktop; @@ -42,6 +43,7 @@ public: int isVisible() { return (m_vis & wVisShow) && ((!m_parent) || m_parent->isVisible()); } /* ... */ + eWidgetAnimation m_animation; private: eWidgetDesktop *m_desktop; diff --git a/lib/gui/ewidgetanimation.cpp b/lib/gui/ewidgetanimation.cpp new file mode 100644 index 00000000..3912d592 --- /dev/null +++ b/lib/gui/ewidgetanimation.cpp @@ -0,0 +1,46 @@ +#include <lib/gui/ewidgetanimation.h> +#include <lib/gui/ewidget.h> + +eWidgetAnimation::eWidgetAnimation(eWidget *widget): m_widget(widget) +{ + m_active = 0; +} + +void eWidgetAnimation::tick(int inc) +{ + if (!m_active) + return; + + // move animation + if (m_move_length) + { + if (m_move_current_tick >= m_move_length) + { + m_active = 0; + m_move_current_tick = m_move_length; + } + int xdiff = m_move_end.x() - m_move_start.x(); + int ydiff = m_move_end.y() - m_move_start.y(); + + xdiff *= m_move_current_tick; + xdiff /= m_move_length; + + ydiff *= m_move_current_tick; + ydiff /= m_move_length; + + ePoint res(m_move_start.x() + xdiff, m_move_start.y() + ydiff); + + m_move_current_tick += inc; + + m_widget->move(res); + } +} + +void eWidgetAnimation::startMoveAnimation(ePoint start, ePoint end, int length) +{ + m_move_current_tick = 0; + m_move_length = length; + m_move_start = start; + m_move_end = end; + m_active = 1; +} diff --git a/lib/gui/ewidgetanimation.h b/lib/gui/ewidgetanimation.h new file mode 100644 index 00000000..61d79e6d --- /dev/null +++ b/lib/gui/ewidgetanimation.h @@ -0,0 +1,25 @@ +#ifndef __lib_gui_ewidgetanimation_h +#define __lib_gui_ewidgetanimation_h + +#include <lib/gdi/esize.h> +#include <lib/gdi/epoint.h> + +class eWidget; + +class eWidgetAnimation +{ +public: + eWidgetAnimation(eWidget *widget); + + void tick(int inc); + + void startMoveAnimation(ePoint start, ePoint end, int length); + + int m_active; +private: + int m_move_current_tick, m_move_length; + ePoint m_move_start, m_move_end; + eWidget *m_widget; +}; + +#endif diff --git a/lib/gui/ewidgetdesktop.cpp b/lib/gui/ewidgetdesktop.cpp index d4a02010..1c65d5d2 100644 --- a/lib/gui/ewidgetdesktop.cpp +++ b/lib/gui/ewidgetdesktop.cpp @@ -1,11 +1,19 @@ #include <lib/gui/ewidgetdesktop.h> #include <lib/gui/ewidget.h> #include <lib/base/ebase.h> +#include <lib/gdi/grc.h> + +extern void dumpRegion(const gRegion ®ion); void eWidgetDesktop::addRootWidget(eWidget *root, int top) { assert(!root->m_desktop); - if (!top) + + /* buffered mode paints back-to-front, while immediate mode is front-to-back. */ + if (m_comp_mode == cmBuffered) + top = !top; + + if (top) m_root.push_back(root); else m_root.push_front(root); @@ -23,13 +31,25 @@ void eWidgetDesktop::removeRootWidget(eWidget *root) m_root.remove(root); } -void eWidgetDesktop::calcWidgetClipRegion(struct eWidgetDesktopCompBuffer *comp, eWidget *widget, gRegion &parent_visible) +int eWidgetDesktop::movedWidget(eWidget *root) +{ + if ((m_comp_mode == cmBuffered) && (root->m_comp_buffer)) + { + root->m_comp_buffer->m_position = root->position(); + redrawComposition(0); + return 0; + } + + return -1; +} + +void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible) { /* start with our clip region, clipped with the parent's */ if (widget->m_vis & eWidget::wVisShow) { widget->m_visible_region = widget->m_clip_region; - widget->m_visible_region.moveBy(widget->position() - comp->m_position); + widget->m_visible_region.moveBy(widget->position()); widget->m_visible_region &= parent_visible; // in parent space! /* TODO: check transparency here! */ @@ -38,42 +58,71 @@ void eWidgetDesktop::calcWidgetClipRegion(struct eWidgetDesktopCompBuffer *comp, /* now prepare for recursing to childs */ widget->m_visible_region.moveBy(-widget->position()); // now in local space - } else widget->m_visible_region = gRegion(); widget->m_visible_with_childs = widget->m_visible_region; for (ePtrList<eWidget>::iterator i(widget->m_childs.begin()); i != widget->m_childs.end(); ++i) - calcWidgetClipRegion(comp, *i, widget->m_visible_region); + if (i->m_vis & eWidget::wVisShow) + calcWidgetClipRegion(*i, widget->m_visible_region); } -void eWidgetDesktop::recalcClipRegions() +void eWidgetDesktop::recalcClipRegions(eWidget *root) { if (m_comp_mode == cmImmediate) - m_screen.m_background_region = gRegion(eRect(ePoint(0, 0), m_screen.m_screen_size)); - - for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i) { - eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer; + gRegion background_before = m_screen.m_background_region; - if (m_comp_mode != cmImmediate) + m_screen.m_background_region = gRegion(eRect(ePoint(0, 0), m_screen.m_screen_size)); + + for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i) { - if (!comp) - { - createBufferForWidget(*i); - comp = i->m_comp_buffer; - } - - comp->m_background_region = gRegion(eRect(ePoint(0, 0), comp->m_screen_size)); + if (!(i->m_vis & eWidget::wVisShow)) + continue; + + gRegion visible_before = i->m_visible_with_childs; + + calcWidgetClipRegion(*i, m_screen.m_background_region); + + gRegion redraw = (i->m_visible_with_childs - visible_before) | (visible_before - i->m_visible_with_childs); + + redraw.moveBy(i->position()); + + invalidate(redraw); } - calcWidgetClipRegion(comp, *i, comp->m_background_region); + gRegion redraw = (background_before - m_screen.m_background_region) | (m_screen.m_background_region - background_before); + invalidate(redraw); + } else + { + if ((!root->m_comp_buffer) || (root->size() != root->m_comp_buffer->m_screen_size)) + createBufferForWidget(root); + + eWidgetDesktopCompBuffer *comp = root->m_comp_buffer; + + gRegion visible_before = root->m_visible_with_childs; + + comp->m_background_region = gRegion(eRect(comp->m_position, comp->m_screen_size)); + + gRegion visible_new = root->m_visible_with_childs - visible_before; + gRegion visible_lost = visible_before - root->m_visible_with_childs; + visible_new.moveBy(root->position()); + visible_lost.moveBy(root->position()); + + /* this sucks, obviously. */ + invalidate(visible_new); + invalidate(visible_lost); + + calcWidgetClipRegion(root, comp->m_background_region); } } void eWidgetDesktop::invalidate(const gRegion ®ion) { + if (region.empty()) + return; + if (m_timer && !m_require_redraw) m_timer->start(0, 1); // start singleshot redraw timer @@ -84,10 +133,12 @@ void eWidgetDesktop::invalidate(const gRegion ®ion) else for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i) { + if (!(i->m_vis & eWidget::wVisShow)) + continue; + eWidgetDesktopCompBuffer *comp = i->m_comp_buffer; gRegion mregion = region; - mregion.moveBy(-comp->m_position); comp->m_dirty_region |= mregion; } } @@ -118,7 +169,7 @@ void eWidgetDesktop::setBackgroundColor(gRGB col) void eWidgetDesktop::setPalette(gPixmap &pm) { - if (m_comp_mode == cmImmediate) +// if (m_comp_mode == cmImmediate) { ASSERT(m_screen.m_dc); gPainter painter(m_screen.m_dc); @@ -160,9 +211,14 @@ void eWidgetDesktop::paint() { eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer; + if (!(i->m_vis & eWidget::wVisShow)) + continue; + { gPainter painter(comp->m_dc); + painter.moveOffset(-comp->m_position); i->doPaint(painter, comp->m_dirty_region); + painter.resetOffset(); } if (m_comp_mode != cmImmediate) @@ -175,13 +231,15 @@ void eWidgetDesktop::paint() if (m_comp_mode == cmBuffered) { eDebug("redraw composition"); - redrawComposition(); + redrawComposition(0); } } void eWidgetDesktop::setDC(gDC *dc) { m_screen.m_dc = dc; + if (m_comp_mode == cmBuffered) + redrawComposition(1); } void eWidgetDesktop::setRedrawTask(eMainloop &ml) @@ -241,6 +299,7 @@ eWidgetDesktop::eWidgetDesktop(eSize size): m_mainloop(0), m_timer(0) m_screen.m_screen_size = size; m_require_redraw = 0; + CONNECT(gRC::getInstance()->notify, eWidgetDesktop::notify); setCompositionMode(cmImmediate); } @@ -256,12 +315,26 @@ void eWidgetDesktop::createBufferForWidget(eWidget *widget) eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer = new eWidgetDesktopCompBuffer; - eRect bbox = widget->m_clip_region.extends; + eDebug("create buffer for widget, %d x %d\n", widget->size().width(), widget->size().height()); + + eRect bbox = eRect(widget->position(), widget->size()); comp->m_position = bbox.topLeft(); comp->m_dirty_region = gRegion(eRect(ePoint(0, 0), bbox.size())); comp->m_screen_size = bbox.size(); /* TODO: configurable bit depth. */ - comp->m_dc = new gDC(new gPixmap(comp->m_screen_size, 32)); + + /* clone palette. FIXME. */ + ePtr<gPixmap> pm = new gPixmap(comp->m_screen_size, 32, 1), pm_screen; + pm->surface->clut.data = new gRGB[256]; + pm->surface->clut.colors = 256; + pm->surface->clut.start = 0; + + + m_screen.m_dc->getPixmap(pm_screen); + + memcpy(pm->surface->clut.data, pm_screen->surface->clut.data, 256 * sizeof(gRGB)); + + comp->m_dc = new gDC(pm); } void eWidgetDesktop::removeBufferForWidget(eWidget *widget) @@ -273,15 +346,41 @@ void eWidgetDesktop::removeBufferForWidget(eWidget *widget) } } -void eWidgetDesktop::redrawComposition() +void eWidgetDesktop::redrawComposition(int notified) { + if (m_comp_mode != cmBuffered) + return; + + assert(m_screen.m_dc); + gPainter p(m_screen.m_dc); - + p.resetClip(eRect(ePoint(0, 0), m_screen.m_screen_size)); + p.setBackgroundColor(m_screen.m_background_color); + p.clear(); + for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i) { + if (!i->isVisible()) + continue; ePtr<gPixmap> pm; ASSERT(i->m_comp_buffer); i->m_comp_buffer->m_dc->getPixmap(pm); - p.blit(pm, i->m_comp_buffer->m_position, eRect(), gPixmap::blitAlphaTest); + p.blit(pm, i->m_comp_buffer->m_position, eRect(), gPixmap::blitAlphaBlend); } + + // flip activates on next vsync. + p.flip(); + p.waitVSync(); + + if (notified) + p.notify(); + + for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i) + if (i->m_animation.m_active) + i->m_animation.tick(1); +} + +void eWidgetDesktop::notify() +{ + redrawComposition(1); } diff --git a/lib/gui/ewidgetdesktop.h b/lib/gui/ewidgetdesktop.h index 58bff50a..117138bd 100644 --- a/lib/gui/ewidgetdesktop.h +++ b/lib/gui/ewidgetdesktop.h @@ -35,7 +35,14 @@ public: ~eWidgetDesktop(); void addRootWidget(eWidget *root, int top); void removeRootWidget(eWidget *root); - void recalcClipRegions(); + + /* try to move widget content. */ + /* returns -1 if there's no move support. */ + /* call this after recalcClipRegions for that widget. */ + /* you probably want to invalidate if -1 was returned. */ + int movedWidget(eWidget *root); + + void recalcClipRegions(eWidget *root); void invalidate(const gRegion ®ion); void paint(); @@ -58,7 +65,7 @@ public: void setCompositionMode(int mode); private: ePtrList<eWidget> m_root; - void calcWidgetClipRegion(eWidgetDesktopCompBuffer *comp, eWidget *widget, gRegion &parent_visible); + void calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible); void paintBackground(eWidgetDesktopCompBuffer *comp); eMainloop *m_mainloop; @@ -72,7 +79,8 @@ private: void createBufferForWidget(eWidget *widget); void removeBufferForWidget(eWidget *widget); - void redrawComposition(); + void redrawComposition(int notifed); + void notify(); }; #endif |
