]> Dogcows Code - chaz/openbox/blob - otk/widget.cc
a859809ff967d6e71bed6c6796d8a4dc72518a27
[chaz/openbox] / 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 OtkEventHandler(),
16 _direction(direction), _stretchable_vert(false), _stretchable_horz(false),
17 _event_dispatcher(parent->getEventDispatcher())
18 {
19 assert(parent);
20 _event_dispatcher->registerHandler(getWindow(), this);
21 }
22
23 OtkWidget::OtkWidget(OtkEventDispatcher *event_dispatcher, Style *style,
24 Direction direction, Cursor cursor, int bevel_width)
25 : OtkBaseWidget(style, cursor, bevel_width),
26 OtkEventHandler(),
27 _direction(direction), _stretchable_vert(false), _stretchable_horz(false),
28 _event_dispatcher(event_dispatcher)
29 {
30 assert(event_dispatcher);
31 _event_dispatcher->registerHandler(getWindow(), this);
32 }
33
34 OtkWidget::~OtkWidget()
35 {
36 _event_dispatcher->clearHandler(_window);
37 }
38
39 void OtkWidget::adjust(void)
40 {
41 if (_direction == Horizontal)
42 adjustHorz();
43 else
44 adjustVert();
45 }
46
47 void OtkWidget::adjustHorz(void)
48 {
49 if (_children.size() == 0)
50 return;
51
52 OtkWidget *tmp;
53 OtkBaseWidgetList::iterator it, end = _children.end();
54
55 int tallest = 0;
56 int width = _bevel_width;
57 OtkBaseWidgetList stretchable;
58
59 for (it = _children.begin(); it != end; ++it) {
60 if (!(tmp = dynamic_cast<OtkWidget*>(*it))) continue;
61 if (tmp->isStretchableVert())
62 tmp->setHeight(_rect.height() > _bevel_width * 2 ?
63 _rect.height() - _bevel_width * 2 : _bevel_width);
64 if (tmp->isStretchableHorz())
65 stretchable.push_back(tmp);
66 else
67 width += tmp->_rect.width() + _bevel_width;
68
69 if (tmp->_rect.height() > tallest)
70 tallest = tmp->_rect.height();
71 }
72
73 if (stretchable.size() > 0) {
74 OtkBaseWidgetList::iterator str_it = stretchable.begin(),
75 str_end = stretchable.end();
76
77 int str_width = _rect.width() - width / stretchable.size();
78
79 for (; str_it != str_end; ++str_it)
80 (*str_it)->setWidth(str_width > _bevel_width ? str_width - _bevel_width
81 : _bevel_width);
82 }
83
84 OtkWidget *prev_widget = 0;
85
86 for (it = _children.begin(); it != end; ++it) {
87 if (!(tmp = dynamic_cast<OtkWidget*>(*it))) continue;
88 int x, y;
89
90 if (prev_widget)
91 x = prev_widget->_rect.x() + prev_widget->_rect.width() + _bevel_width;
92 else
93 x = _rect.x() + _bevel_width;
94 y = (tallest - tmp->_rect.height()) / 2 + _bevel_width;
95
96 tmp->move(x, y);
97
98 prev_widget = tmp;
99 }
100
101 internalResize(width, tallest + _bevel_width * 2);
102 }
103
104 void OtkWidget::adjustVert(void)
105 {
106 if (_children.size() == 0)
107 return;
108
109 OtkWidget *tmp;
110 OtkBaseWidgetList::iterator it, end = _children.end();
111
112 int widest = 0;
113 int height = _bevel_width;
114 OtkBaseWidgetList stretchable;
115
116 for (it = _children.begin(); it != end; ++it) {
117 if (!(tmp = dynamic_cast<OtkWidget*>(*it))) continue;
118 if (tmp->isStretchableHorz())
119 tmp->setWidth(_rect.width() > _bevel_width * 2 ?
120 _rect.width() - _bevel_width * 2 : _bevel_width);
121 if (tmp->isStretchableVert())
122 stretchable.push_back(tmp);
123 else
124 height += tmp->_rect.height() + _bevel_width;
125
126 if (tmp->_rect.width() > widest)
127 widest = tmp->_rect.width();
128 }
129
130 if (stretchable.size() > 0) {
131 OtkBaseWidgetList::iterator str_it = stretchable.begin(),
132 str_end = stretchable.end();
133
134 int str_height = _rect.height() - height / stretchable.size();
135
136 for (; str_it != str_end; ++str_it)
137 (*str_it)->setHeight(str_height > _bevel_width ?
138 str_height - _bevel_width : _bevel_width);
139 }
140
141 OtkWidget *prev_widget = 0;
142
143 for (it = _children.begin(); it != end; ++it) {
144 if (!(tmp = dynamic_cast<OtkWidget*>(*it))) continue;
145 int x, y;
146
147 if (prev_widget)
148 y = prev_widget->_rect.y() + prev_widget->_rect.height() + _bevel_width;
149 else
150 y = _rect.y() + _bevel_width;
151 x = (widest - tmp->_rect.width()) / 2 + _bevel_width;
152
153 tmp->move(x, y);
154
155 prev_widget = tmp;
156 }
157
158 internalResize(widest + _bevel_width * 2, height);
159 }
160
161 void OtkWidget::update(void)
162 {
163 if (_dirty)
164 adjust();
165
166 OtkBaseWidget::update();
167 }
168
169 void OtkWidget::internalResize(int w, int h)
170 {
171 assert(w > 0 && h > 0);
172
173 // if (! _fixed_width && ! _fixed_height)
174 resize(w, h);
175 // else if (! _fixed_width)
176 // resize(w, _rect.height());
177 // else if (! _fixed_height)
178 // resize(_rect.width(), h);
179 }
180
181 void OtkWidget::setEventDispatcher(OtkEventDispatcher *disp)
182 {
183 if (_event_dispatcher)
184 _event_dispatcher->clearHandler(_window);
185 _event_dispatcher = disp;
186 _event_dispatcher->registerHandler(_window, this);
187 }
188
189 void OtkWidget::exposeHandler(const XExposeEvent &e)
190 {
191 OtkEventHandler::exposeHandler(e);
192 _dirty = true;
193 update();
194 }
195
196 void OtkWidget::configureHandler(const XConfigureEvent &e)
197 {
198 OtkEventHandler::configureHandler(e);
199 if (_ignore_config) {
200 _ignore_config--;
201 } else {
202 if (!(e.width == _rect.width() && e.height == _rect.height())) {
203 _dirty = true;
204 _rect.setSize(e.width, e.height);
205 }
206 update();
207 }
208 }
209
210 }
This page took 0.044711 seconds and 4 git commands to generate.