00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "elements/CEGUIScrollablePane.h"
00025 #include "elements/CEGUIScrolledContainer.h"
00026 #include "elements/CEGUIScrollbar.h"
00027 #include "CEGUIWindowManager.h"
00028 #include <math.h>
00029
00030
00031 namespace CEGUI
00032 {
00034
00035 const String ScrollablePane::EventNamespace("ScrollablePane");
00036 const String ScrollablePane::EventContentPaneChanged("ContentPaneChanged");
00037 const String ScrollablePane::EventVertScrollbarModeChanged("VertScrollbarModeChanged");
00038 const String ScrollablePane::EventHorzScrollbarModeChanged("HorzScrollbarModeChanged");
00039 const String ScrollablePane::EventAutoSizeSettingChanged("AutoSizeSettingChanged");
00040 const String ScrollablePane::EventContentPaneScrolled("ContentPaneScrolled");
00041
00042 ScrollablePaneProperties::ForceHorzScrollbar ScrollablePane::d_horzScrollbarProperty;
00043 ScrollablePaneProperties::ForceVertScrollbar ScrollablePane::d_vertScrollbarProperty;
00044 ScrollablePaneProperties::ContentPaneAutoSized ScrollablePane::d_autoSizedProperty;
00045 ScrollablePaneProperties::ContentArea ScrollablePane::d_contentAreaProperty;
00046 ScrollablePaneProperties::HorzStepSize ScrollablePane::d_horzStepProperty;
00047 ScrollablePaneProperties::HorzOverlapSize ScrollablePane::d_horzOverlapProperty;
00048 ScrollablePaneProperties::HorzScrollPosition ScrollablePane::d_horzScrollPositionProperty;
00049 ScrollablePaneProperties::VertStepSize ScrollablePane::d_vertStepProperty;
00050 ScrollablePaneProperties::VertOverlapSize ScrollablePane::d_vertOverlapProperty;
00051 ScrollablePaneProperties::VertScrollPosition ScrollablePane::d_vertScrollPositionProperty;
00053
00054 ScrollablePane::ScrollablePane(const String& type, const String& name) :
00055 Window(type, name),
00056 d_forceVertScroll(false),
00057 d_forceHorzScroll(false),
00058 d_contentRect(0, 0, 0, 0),
00059 d_vertStep(0.1f),
00060 d_vertOverlap(0.01f),
00061 d_horzStep(0.1f),
00062 d_horzOverlap(0.01f),
00063 d_vertScrollbar(0),
00064 d_horzScrollbar(0),
00065 d_container(0)
00066 {
00067 addScrollablePaneEvents();
00068 addScrollablePaneProperties();
00069 }
00070
00071 ScrollablePane::~ScrollablePane(void)
00072 {
00073 }
00074
00075 const ScrolledContainer* ScrollablePane::getContentPane(void) const
00076 {
00077 assert (d_container != 0);
00078 return d_container;
00079 }
00080
00081 bool ScrollablePane::isVertScrollbarAlwaysShown(void) const
00082 {
00083 return d_forceVertScroll;
00084 }
00085
00086 void ScrollablePane::setShowVertScrollbar(bool setting)
00087 {
00088 if (d_forceVertScroll != setting)
00089 {
00090 d_forceVertScroll = setting;
00091
00092 configureScrollbars();
00093 WindowEventArgs args(this);
00094 onVertScrollbarModeChanged(args);
00095 }
00096 }
00097
00098 bool ScrollablePane::isHorzScrollbarAlwaysShown(void) const
00099 {
00100 return d_forceHorzScroll;
00101 }
00102
00103 void ScrollablePane::setShowHorzScrollbar(bool setting)
00104 {
00105 if (d_forceHorzScroll != setting)
00106 {
00107 d_forceHorzScroll = setting;
00108
00109 configureScrollbars();
00110 WindowEventArgs args(this);
00111 onHorzScrollbarModeChanged(args);
00112 }
00113 }
00114
00115 bool ScrollablePane::isContentPaneAutoSized(void) const
00116 {
00117 assert(d_container != 0);
00118 return d_container->isContentPaneAutoSized();
00119 }
00120
00121 void ScrollablePane::setContentPaneAutoSized(bool setting)
00122 {
00123 assert(d_container != 0);
00124 d_container->setContentPaneAutoSized(setting);
00125 }
00126
00127 const Rect& ScrollablePane::getContentPaneArea(void) const
00128 {
00129 assert(d_container != 0);
00130 return d_container->getContentArea();
00131 }
00132
00133 void ScrollablePane::setContentPaneArea(const Rect& area)
00134 {
00135 assert(d_container != 0);
00136 d_container->setContentArea(area);
00137 }
00138
00139 float ScrollablePane::getHorizontalStepSize(void) const
00140 {
00141 return d_horzStep;
00142 }
00143
00144 void ScrollablePane::setHorizontalStepSize(float step)
00145 {
00146 d_horzStep = step;
00147 configureScrollbars();
00148 }
00149
00150 float ScrollablePane::getHorizontalOverlapSize(void) const
00151 {
00152 return d_horzOverlap;
00153 }
00154
00155 void ScrollablePane::setHorizontalOverlapSize(float overlap)
00156 {
00157 d_horzOverlap = overlap;
00158 configureScrollbars();
00159 }
00160
00161 float ScrollablePane::getHorizontalScrollPosition(void) const
00162 {
00163 assert(d_horzScrollbar != 0);
00164 float docSz = d_horzScrollbar->getDocumentSize();
00165 return (docSz != 0) ? d_horzScrollbar->getScrollPosition() / docSz : 0.0f;
00166 }
00167
00168 void ScrollablePane::setHorizontalScrollPosition(float position)
00169 {
00170 assert(d_horzScrollbar != 0);
00171 d_horzScrollbar->setScrollPosition(d_horzScrollbar->getDocumentSize() * position);
00172 }
00173
00174 float ScrollablePane::getVerticalStepSize(void) const
00175 {
00176 return d_vertStep;
00177 }
00178
00179 void ScrollablePane::setVerticalStepSize(float step)
00180 {
00181 d_vertStep = step;
00182 configureScrollbars();
00183 }
00184
00185 float ScrollablePane::getVerticalOverlapSize(void) const
00186 {
00187 return d_vertOverlap;
00188 }
00189
00190 void ScrollablePane::setVerticalOverlapSize(float overlap)
00191 {
00192 d_vertOverlap = overlap;
00193 configureScrollbars();
00194 }
00195
00196 float ScrollablePane::getVerticalScrollPosition(void) const
00197 {
00198 assert(d_vertScrollbar != 0);
00199 float docSz = d_vertScrollbar->getDocumentSize();
00200 return (docSz != 0) ? d_vertScrollbar->getScrollPosition() / docSz : 0.0f;
00201 }
00202
00203 void ScrollablePane::setVerticalScrollPosition(float position)
00204 {
00205 assert(d_vertScrollbar != 0);
00206 d_vertScrollbar->setScrollPosition(d_vertScrollbar->getDocumentSize() * position);
00207 }
00208
00209 void ScrollablePane::initialise(void)
00210 {
00211 String widgetName;
00212
00213 widgetName = d_name + "__auto_hscrollbar__";
00214 d_horzScrollbar = createHorizontalScrollbar(widgetName);
00215
00216 assert(d_horzScrollbar != 0);
00217 assert(d_horzScrollbar->getName() == widgetName);
00218
00219
00220 widgetName = d_name + "__auto_vscrollbar__";
00221 d_vertScrollbar = createVerticalScrollbar(widgetName);
00222
00223 assert(d_vertScrollbar != 0);
00224 assert(d_vertScrollbar->getName() == widgetName);
00225
00226
00227 d_container =
00228 static_cast<ScrolledContainer*>(WindowManager::getSingleton().createWindow(
00229 ScrolledContainer::WidgetTypeName, d_name + "__auto_container__"));
00230
00231
00232 addChildWindow(d_horzScrollbar);
00233 addChildWindow(d_vertScrollbar);
00234 addChildWindow(d_container);
00235
00236
00237 d_horzScrollbar->setAlwaysOnTop(true);
00238 d_vertScrollbar->setAlwaysOnTop(true);
00239
00240
00241 d_container->setSize(Relative, Size(1.0f, 1.0f));
00242
00243
00244 d_vertScrollbar->subscribeEvent(
00245 Scrollbar::EventScrollPositionChanged,
00246 Event::Subscriber(&ScrollablePane::handleScrollChange, this));
00247 d_horzScrollbar->subscribeEvent(
00248 Scrollbar::EventScrollPositionChanged,
00249 Event::Subscriber(&ScrollablePane::handleScrollChange, this));
00250 d_container->subscribeEvent(
00251 ScrolledContainer::EventContentChanged,
00252 Event::Subscriber(&ScrollablePane::handleContentAreaChange, this));
00253 d_container->subscribeEvent(
00254 ScrolledContainer::EventAutoSizeSettingChanged,
00255 Event::Subscriber(&ScrollablePane::handleAutoSizePaneChanged, this));
00256
00257
00258 configureScrollbars();
00259 }
00260
00261 void ScrollablePane::addScrollablePaneEvents(void)
00262 {
00263 addEvent(EventAutoSizeSettingChanged);
00264 addEvent(EventContentPaneChanged);
00265 addEvent(EventHorzScrollbarModeChanged);
00266 addEvent(EventVertScrollbarModeChanged);
00267 addEvent(EventContentPaneScrolled);
00268 }
00269
00270 void ScrollablePane::configureScrollbars(void)
00271 {
00272
00273 assert(d_container != 0);
00274 assert(d_vertScrollbar != 0);
00275 assert(d_horzScrollbar != 0);
00276
00277
00278 d_vertScrollbar->setVisible(isVertScrollbarNeeded());
00279 d_horzScrollbar->setVisible(isHorzScrollbarNeeded());
00280
00281
00282
00283 if (d_horzScrollbar->isVisible())
00284 {
00285 d_vertScrollbar->setVisible(isVertScrollbarNeeded());
00286 }
00287
00288 performChildWindowLayout();
00289
00290
00291 Rect viewableArea(getViewableArea());
00292
00293
00294 d_vertScrollbar->setDocumentSize(fabsf(d_contentRect.getHeight()));
00295 d_vertScrollbar->setPageSize(viewableArea.getHeight());
00296 d_vertScrollbar->setStepSize(ceguimax(1.0f, viewableArea.getHeight() * d_vertStep));
00297 d_vertScrollbar->setOverlapSize(ceguimax(1.0f, viewableArea.getHeight() * d_vertOverlap));
00298 d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition());
00299
00300
00301 d_horzScrollbar->setDocumentSize(fabsf(d_contentRect.getWidth()));
00302 d_horzScrollbar->setPageSize(viewableArea.getWidth());
00303 d_horzScrollbar->setStepSize(ceguimax(1.0f, viewableArea.getWidth() * d_horzStep));
00304 d_horzScrollbar->setOverlapSize(ceguimax(1.0f, viewableArea.getWidth() * d_horzOverlap));
00305 d_horzScrollbar->setScrollPosition(d_horzScrollbar->getScrollPosition());
00306 }
00307
00308 bool ScrollablePane::isHorzScrollbarNeeded(void) const
00309 {
00310 assert(d_container != 0);
00311
00312 return ((fabs(d_contentRect.getWidth()) > getViewableArea().getWidth()) || d_forceHorzScroll);
00313 }
00314
00315 bool ScrollablePane::isVertScrollbarNeeded(void) const
00316 {
00317 assert(d_container != 0);
00318
00319 return ((fabs(d_contentRect.getHeight()) > getViewableArea().getHeight()) || d_forceVertScroll);
00320 }
00321
00322 void ScrollablePane::updateContainerPosition(void)
00323 {
00324 assert(d_container != 0);
00325 assert(d_horzScrollbar != 0);
00326 assert(d_vertScrollbar != 0);
00327
00328
00329
00330 Point basePos(-d_horzScrollbar->getScrollPosition(), -d_vertScrollbar->getScrollPosition());
00331
00332
00333
00334 Point bias(d_contentRect.d_left, d_contentRect.d_top);
00335
00336
00337
00338 d_container->setPosition(Absolute, basePos - bias);
00339 }
00340
00341 void ScrollablePane::onContentPaneChanged(WindowEventArgs& e)
00342 {
00343 fireEvent(EventContentPaneChanged, e, EventNamespace);
00344 }
00345
00346 void ScrollablePane::onVertScrollbarModeChanged(WindowEventArgs& e)
00347 {
00348 fireEvent(EventVertScrollbarModeChanged, e, EventNamespace);
00349 }
00350
00351 void ScrollablePane::onHorzScrollbarModeChanged(WindowEventArgs& e)
00352 {
00353 fireEvent(EventHorzScrollbarModeChanged, e, EventNamespace);
00354 }
00355
00356 void ScrollablePane::onAutoSizeSettingChanged(WindowEventArgs& e)
00357 {
00358 fireEvent(EventAutoSizeSettingChanged, e, EventNamespace);
00359 }
00360
00361 void ScrollablePane::onContentPaneScrolled(WindowEventArgs& e)
00362 {
00363 updateContainerPosition();
00364 fireEvent(EventContentPaneScrolled, e, EventNamespace);
00365 }
00366
00367 bool ScrollablePane::handleScrollChange(const EventArgs& e)
00368 {
00369 WindowEventArgs args(this);
00370 onContentPaneScrolled(args);
00371 return true;
00372 }
00373
00374 bool ScrollablePane::handleContentAreaChange(const EventArgs& e)
00375 {
00376 assert(d_container != 0);
00377 assert(d_horzScrollbar != 0);
00378 assert(d_vertScrollbar != 0);
00379
00380
00381 Rect contentArea(d_container->getContentArea());
00382
00383
00384 float xChange = contentArea.d_left - d_contentRect.d_left;
00385 float yChange = contentArea.d_top - d_contentRect.d_top;
00386
00387
00388 d_contentRect = contentArea;
00389
00390 configureScrollbars();
00391
00392
00393 d_horzScrollbar->setScrollPosition(d_horzScrollbar->getScrollPosition() - xChange);
00394 d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition() - yChange);
00395
00396
00397
00398
00399 if (xChange || yChange)
00400 {
00401 updateContainerPosition();
00402 }
00403
00404
00405 WindowEventArgs args(this);
00406 onContentPaneChanged(args);
00407
00408 return true;
00409 }
00410
00411 bool ScrollablePane::handleAutoSizePaneChanged(const EventArgs& e)
00412 {
00413
00414 WindowEventArgs args(this);
00415 fireEvent(EventAutoSizeSettingChanged, args, EventNamespace);
00416 return args.handled;
00417 }
00418
00419 void ScrollablePane::addChild_impl(Window* wnd)
00420 {
00421
00422 assert(wnd != 0);
00423
00424
00425 if (wnd->getName().find("__auto_") != String::npos)
00426 {
00427
00428 Window::addChild_impl(wnd);
00429 }
00430
00431 else
00432 {
00433
00434 assert(d_container != 0);
00435 d_container->addChildWindow(wnd);
00436 }
00437 }
00438
00439 void ScrollablePane::removeChild_impl(Window* wnd)
00440 {
00441
00442 assert(wnd != 0);
00443
00444
00445 if (wnd->getName().find("__auto_") != String::npos)
00446 {
00447
00448 Window::removeChild_impl(wnd);
00449 }
00450
00451 else
00452 {
00453
00454 assert(d_container != 0);
00455 d_container->removeChildWindow(wnd);
00456 }
00457 }
00458
00459 void ScrollablePane::onSized(WindowEventArgs& e)
00460 {
00461 Window::onSized(e);
00462 configureScrollbars();
00463 updateContainerPosition();
00464
00465 e.handled = true;
00466 }
00467
00468 void ScrollablePane::onMouseWheel(MouseEventArgs& e)
00469 {
00470
00471 Window::onMouseWheel(e);
00472
00473 if (d_vertScrollbar->isVisible() && (d_vertScrollbar->getDocumentSize() > d_vertScrollbar->getPageSize()))
00474 {
00475 d_vertScrollbar->setScrollPosition(d_vertScrollbar->getScrollPosition() + d_vertScrollbar->getStepSize() * -e.wheelChange);
00476 }
00477 else if (d_horzScrollbar->isVisible() && (d_horzScrollbar->getDocumentSize() > d_horzScrollbar->getPageSize()))
00478 {
00479 d_horzScrollbar->setScrollPosition(d_horzScrollbar->getScrollPosition() + d_horzScrollbar->getStepSize() * -e.wheelChange);
00480 }
00481
00482 e.handled = true;
00483 }
00484
00485 void ScrollablePane::addScrollablePaneProperties(void)
00486 {
00487 addProperty(&d_horzScrollbarProperty);
00488 addProperty(&d_vertScrollbarProperty);
00489 addProperty(&d_autoSizedProperty);
00490 addProperty(&d_contentAreaProperty);
00491 addProperty(&d_horzStepProperty);
00492 addProperty(&d_horzOverlapProperty);
00493 addProperty(&d_horzScrollPositionProperty);
00494 addProperty(&d_vertStepProperty);
00495 addProperty(&d_vertOverlapProperty);
00496 addProperty(&d_vertScrollPositionProperty);
00497 }
00498
00499 }