move event handling into basewidget again <FLINCH>
[mikachu/openbox.git] / otk / widget.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef    HAVE_CONFIG_H
4 #  include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 #include "widget.hh"
8
9 #include <algorithm>
10
11 namespace otk {
12
13 OtkWidget::OtkWidget(OtkWidget *parent, Direction direction)
14   : OtkBaseWidget(parent),
15     _direction(direction), _stretchable_vert(false), _stretchable_horz(false),
16     _event_dispatcher(parent->getEventDispatcher())
17 {
18   assert(parent);
19   _event_dispatcher->registerHandler(getWindow(), this);
20 }
21
22 OtkWidget::OtkWidget(OtkEventDispatcher *event_dispatcher, Style *style,
23                      Direction direction, Cursor cursor, int bevel_width)
24   : OtkBaseWidget(style, cursor, bevel_width),
25     _direction(direction), _stretchable_vert(false), _stretchable_horz(false),
26     _event_dispatcher(event_dispatcher)
27 {
28   assert(event_dispatcher);
29   _event_dispatcher->registerHandler(getWindow(), this);
30 }
31
32 OtkWidget::~OtkWidget()
33 {
34   _event_dispatcher->clearHandler(_window);
35 }
36
37 void OtkWidget::adjust(void)
38 {
39   if (_direction == Horizontal)
40     adjustHorz();
41   else
42     adjustVert();
43 }
44
45 void OtkWidget::adjustHorz(void)
46 {
47   if (_children.size() == 0)
48     return;
49
50   OtkWidget *tmp;
51   OtkBaseWidgetList::iterator it, end = _children.end();
52
53   int tallest = 0;
54   int width = _bevel_width;
55   OtkBaseWidgetList stretchable;
56
57   for (it = _children.begin(); it != end; ++it) {
58     if (!(tmp = dynamic_cast<OtkWidget*>(*it))) continue;
59     if (tmp->isStretchableVert())
60       tmp->setHeight(_rect.height() > _bevel_width * 2 ?
61                      _rect.height() - _bevel_width * 2 : _bevel_width);
62     if (tmp->isStretchableHorz())
63       stretchable.push_back(tmp);
64     else
65       width += tmp->_rect.width() + _bevel_width;
66
67     if (tmp->_rect.height() > tallest)
68       tallest = tmp->_rect.height();
69   }
70
71   if (stretchable.size() > 0) {
72     OtkBaseWidgetList::iterator str_it = stretchable.begin(),
73       str_end = stretchable.end();
74
75     int str_width = _rect.width() - width / stretchable.size();
76
77     for (; str_it != str_end; ++str_it)
78       (*str_it)->setWidth(str_width > _bevel_width ? str_width - _bevel_width
79                           : _bevel_width);
80   }
81
82   OtkWidget *prev_widget = 0;
83
84   for (it = _children.begin(); it != end; ++it) {
85     if (!(tmp = dynamic_cast<OtkWidget*>(*it))) continue;
86     int x, y;
87
88     if (prev_widget)
89       x = prev_widget->_rect.x() + prev_widget->_rect.width() + _bevel_width;
90     else
91       x = _rect.x() + _bevel_width;
92     y = (tallest - tmp->_rect.height()) / 2 + _bevel_width;
93
94     tmp->move(x, y);
95
96     prev_widget = tmp;
97   }
98
99   internalResize(width, tallest + _bevel_width * 2);
100 }
101
102 void OtkWidget::adjustVert(void)
103 {
104   if (_children.size() == 0)
105     return;
106
107   OtkWidget *tmp;
108   OtkBaseWidgetList::iterator it, end = _children.end();
109
110   int widest = 0;
111   int height = _bevel_width;
112   OtkBaseWidgetList stretchable;
113
114   for (it = _children.begin(); it != end; ++it) {
115     if (!(tmp = dynamic_cast<OtkWidget*>(*it))) continue;
116     if (tmp->isStretchableHorz())
117       tmp->setWidth(_rect.width() > _bevel_width * 2 ?
118                     _rect.width() - _bevel_width * 2 : _bevel_width);
119     if (tmp->isStretchableVert())
120       stretchable.push_back(tmp);
121     else
122       height += tmp->_rect.height() + _bevel_width;
123
124     if (tmp->_rect.width() > widest)
125       widest = tmp->_rect.width();
126   }
127
128   if (stretchable.size() > 0) {
129     OtkBaseWidgetList::iterator str_it = stretchable.begin(),
130       str_end = stretchable.end();
131
132     int str_height = _rect.height() - height / stretchable.size();
133
134     for (; str_it != str_end; ++str_it)
135       (*str_it)->setHeight(str_height > _bevel_width ?
136                            str_height - _bevel_width : _bevel_width);
137   }
138
139   OtkWidget *prev_widget = 0;
140
141   for (it = _children.begin(); it != end; ++it) {
142     if (!(tmp = dynamic_cast<OtkWidget*>(*it))) continue;
143     int x, y;
144
145     if (prev_widget)
146       y = prev_widget->_rect.y() + prev_widget->_rect.height() + _bevel_width;
147     else
148       y = _rect.y() + _bevel_width;
149     x = (widest - tmp->_rect.width()) / 2 + _bevel_width;
150
151     tmp->move(x, y);
152
153     prev_widget = tmp;
154   }
155
156   internalResize(widest + _bevel_width * 2, height);
157 }
158
159 void OtkWidget::update(void)
160 {
161   if (_dirty)
162     adjust();
163
164   OtkBaseWidget::update();
165 }
166
167 void OtkWidget::internalResize(int w, int h)
168 {
169   assert(w > 0 && h > 0);
170
171 //  if (! _fixed_width && ! _fixed_height)
172     resize(w, h);
173 //  else if (! _fixed_width)
174 //    resize(w, _rect.height());
175 //  else if (! _fixed_height)
176 //    resize(_rect.width(), h);
177 }
178
179 void OtkWidget::setEventDispatcher(OtkEventDispatcher *disp)
180 {
181   if (_event_dispatcher)
182     _event_dispatcher->clearHandler(_window);
183   _event_dispatcher = disp;
184   _event_dispatcher->registerHandler(_window, this);
185 }
186
187
188 }