Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

CEGUIListHeaderSegment.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002         filename:       CEGUIListHeaderSegment.cpp
00003         created:        15/6/2004
00004         author:         Paul D Turner
00005         
00006         purpose:        Implementation of List header segment widget.
00007 *************************************************************************/
00008 /*************************************************************************
00009     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00010     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00011 
00012     This library is free software; you can redistribute it and/or
00013     modify it under the terms of the GNU Lesser General Public
00014     License as published by the Free Software Foundation; either
00015     version 2.1 of the License, or (at your option) any later version.
00016 
00017     This library is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020     Lesser General Public License for more details.
00021 
00022     You should have received a copy of the GNU Lesser General Public
00023     License along with this library; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 *************************************************************************/
00026 #include "elements/CEGUIListHeaderSegment.h"
00027 #include "CEGUIMouseCursor.h"
00028 
00029 
00030 // Start of CEGUI namespace section
00031 namespace CEGUI
00032 {
00033 const String ListHeaderSegment::EventNamespace("ListHeaderSegment");
00034 
00035 /*************************************************************************
00036         Properties for this class
00037 *************************************************************************/
00038 ListHeaderSegmentProperties::Clickable          ListHeaderSegment::d_clickableProperty;
00039 ListHeaderSegmentProperties::Dragable           ListHeaderSegment::d_dragableProperty;
00040 ListHeaderSegmentProperties::Sizable            ListHeaderSegment::d_sizableProperty;
00041 ListHeaderSegmentProperties::SortDirection      ListHeaderSegment::d_sortDirectionProperty;
00042 
00043 
00044 /*************************************************************************
00045         Constants
00046 *************************************************************************/
00047 // Event names
00048 const String ListHeaderSegment::EventSegmentClicked( (utf8*)"SegmentClicked" );
00049 const String ListHeaderSegment::EventSplitterDoubleClicked( (utf8*)"SplitterDoubleClicked" );
00050 const String ListHeaderSegment::EventSizingSettingChanged( (utf8*)"SizingSettingChanged" );
00051 const String ListHeaderSegment::EventSortDirectionChanged( (utf8*)"SortDirectionChanged" );
00052 const String ListHeaderSegment::EventMovableSettingChanged( (utf8*)"MovableSettingChanged" );
00053 const String ListHeaderSegment::EventSegmentDragStart( (utf8*)"SegmentDragStart" );
00054 const String ListHeaderSegment::EventSegmentDragStop( (utf8*)"SegmentDragStop" );
00055 const String ListHeaderSegment::EventSegmentDragPositionChanged( (utf8*)"SegmentDragPositionChanged" );
00056 const String ListHeaderSegment::EventSegmentSized( (utf8*)"SegmentSized" );
00057 const String ListHeaderSegment::EventClickableSettingChanged( (utf8*)"ClickableSettingChanged" );
00058 
00059 // Defaults
00060 const float     ListHeaderSegment::DefaultSizingArea    = 8.0f;
00061 const float     ListHeaderSegment::SegmentMoveThreshold = 12.0f;
00062 
00063 
00064 /*************************************************************************
00065         Constructor for list header segment base class  
00066 *************************************************************************/
00067 ListHeaderSegment::ListHeaderSegment(const String& type, const String& name) :
00068         Window(type, name),
00069         d_normalMouseCursor(NULL),
00070         d_sizingMouseCursor(NULL),
00071         d_movingMouseCursor(NULL),
00072         d_splitterSize(DefaultSizingArea),
00073         d_splitterHover(false),
00074         d_dragSizing(false),
00075         d_sortDir(None),
00076         d_segmentHover(false),
00077         d_segmentPushed(false),
00078         d_sizingEnabled(true),
00079         d_movingEnabled(true),
00080         d_dragMoving(false),
00081         d_allowClicks(true)
00082 {
00083         addHeaderSegmentEvents();
00084         addHeaderSegmentProperties();
00085 }
00086 
00087 
00088 /*************************************************************************
00089         Destructor for list header segment base class.  
00090 *************************************************************************/
00091 ListHeaderSegment::~ListHeaderSegment(void)
00092 {
00093 }
00094 
00095 
00096 /*************************************************************************
00097         Set whether this segment can be sized.
00098 *************************************************************************/
00099 void ListHeaderSegment::setSizingEnabled(bool setting)
00100 {
00101         if (d_sizingEnabled != setting)
00102         {
00103                 d_sizingEnabled = setting;
00104 
00105                 // if sizing is now disabled, ensure sizing operation is cancelled
00106                 if (!d_sizingEnabled && d_dragSizing)
00107                 {
00108                         releaseInput();
00109                 }
00110 
00111                 WindowEventArgs args(this);
00112                 onSizingSettingChanged(args);
00113         }
00114 
00115 }
00116 
00117 
00118 /*************************************************************************
00119         Set the current sort direction set for this segment.    
00120 *************************************************************************/
00121 void ListHeaderSegment::setSortDirection(SortDirection sort_dir)
00122 {
00123         if (d_sortDir != sort_dir)
00124         {
00125                 d_sortDir = sort_dir;
00126 
00127                 WindowEventArgs args(this);
00128                 onSortDirectionChanged(args);
00129 
00130                 requestRedraw();
00131         }
00132 
00133 }
00134 
00135 
00136 /*************************************************************************
00137         Set whether drag moving is allowed for this segment.    
00138 *************************************************************************/
00139 void ListHeaderSegment::setDragMovingEnabled(bool setting)
00140 {
00141         if (d_movingEnabled != setting)
00142         {
00143                 d_movingEnabled = setting;
00144 
00145                 WindowEventArgs args(this);
00146                 onMovableSettingChanged(args);
00147         }
00148 
00149 }
00150 
00151 
00152 /*************************************************************************
00153         Set whether the segment is clickable.
00154 *************************************************************************/
00155 void ListHeaderSegment::setClickable(bool setting)
00156 {
00157         if (d_allowClicks != setting)
00158         {
00159                 d_allowClicks = setting;
00160 
00161                 WindowEventArgs args(this);
00162                 onClickableSettingChanged(args);
00163         }
00164 
00165 }
00166 
00167 
00168 /*************************************************************************
00169         Add list header segment specific events
00170 *************************************************************************/
00171 void ListHeaderSegment::addHeaderSegmentEvents(void)
00172 {
00173         addEvent(EventSortDirectionChanged);
00174         addEvent(EventSizingSettingChanged);
00175         addEvent(EventSplitterDoubleClicked);
00176         addEvent(EventSegmentClicked);
00177         addEvent(EventSegmentDragStart);
00178         addEvent(EventSegmentDragStop);
00179         addEvent(EventSegmentDragPositionChanged);
00180         addEvent(EventMovableSettingChanged);
00181         addEvent(EventSegmentSized);
00182         addEvent(EventClickableSettingChanged);
00183 }
00184 
00185 
00186 
00187 /*************************************************************************
00188         Handler called when segment is clicked. 
00189 *************************************************************************/
00190 void ListHeaderSegment::onSegmentClicked(WindowEventArgs& e)
00191 {
00192         fireEvent(EventSegmentClicked, e, EventNamespace);
00193 }
00194 
00195 
00196 /*************************************************************************
00197         Handler called when the sizer/splitter is double-clicked.       
00198 *************************************************************************/
00199 void ListHeaderSegment::onSplitterDoubleClicked(WindowEventArgs& e)
00200 {
00201         fireEvent(EventSplitterDoubleClicked, e, EventNamespace);
00202 }
00203 
00204 
00205 /*************************************************************************
00206         Handler called when sizing setting changes.
00207 *************************************************************************/
00208 void ListHeaderSegment::onSizingSettingChanged(WindowEventArgs& e)
00209 {
00210         fireEvent(EventSizingSettingChanged, e, EventNamespace);
00211 }
00212 
00213 
00214 /*************************************************************************
00215         Handler called when the sort direction value changes.
00216 *************************************************************************/
00217 void ListHeaderSegment::onSortDirectionChanged(WindowEventArgs& e)
00218 {
00219         requestRedraw();
00220         fireEvent(EventSortDirectionChanged, e, EventNamespace);
00221 }
00222 
00223 
00224 /*************************************************************************
00225         Handler called when the drag-movable setting is changed.
00226 *************************************************************************/
00227 void ListHeaderSegment::onMovableSettingChanged(WindowEventArgs& e)
00228 {
00229         fireEvent(EventMovableSettingChanged, e, EventNamespace);
00230 }
00231 
00232 
00233 /*************************************************************************
00234         Handler called when the user starts dragging the segment.
00235 *************************************************************************/
00236 void ListHeaderSegment::onSegmentDragStart(WindowEventArgs& e)
00237 {
00238         fireEvent(EventSegmentDragStart, e, EventNamespace);
00239 }
00240 
00241 
00242 /*************************************************************************
00243         Handler called when the user stops dragging the segment
00244         (releases mouse button)
00245 *************************************************************************/
00246 void ListHeaderSegment::onSegmentDragStop(WindowEventArgs& e)
00247 {
00248         fireEvent(EventSegmentDragStop, e, EventNamespace);
00249 }
00250 
00251 
00252 /*************************************************************************
00253         Handler called when the drag position changes.
00254 *************************************************************************/
00255 void ListHeaderSegment::onSegmentDragPositionChanged(WindowEventArgs& e)
00256 {
00257         requestRedraw();
00258         fireEvent(EventSegmentDragPositionChanged, e, EventNamespace);
00259 }
00260 
00261 
00262 /*************************************************************************
00263         Handler called when the segment is sized.
00264 *************************************************************************/
00265 void ListHeaderSegment::onSegmentSized(WindowEventArgs& e)
00266 {
00267         requestRedraw();
00268         fireEvent(EventSegmentSized, e, EventNamespace);
00269 }
00270 
00271 
00272 /*************************************************************************
00273         Handler called when the clickable setting for the segment changes
00274 *************************************************************************/
00275 void ListHeaderSegment::onClickableSettingChanged(WindowEventArgs& e)
00276 {
00277         fireEvent(EventClickableSettingChanged, e, EventNamespace);
00278 }
00279 
00280 
00281 /*************************************************************************
00282         Processing for drag-sizing the segment
00283 *************************************************************************/
00284 void ListHeaderSegment::doDragSizing(const Point& local_mouse)
00285 {
00286         // calculate sizing delta.
00287         float   deltaX = local_mouse.d_x - d_dragPoint.d_x;
00288 
00289         // limit size to within max/min values
00290         float width = d_abs_area.getWidth();
00291 
00292         if ((width + deltaX) < d_minSize.d_width) {
00293                 deltaX = d_minSize.d_width - width;
00294         }
00295         else if ((width + deltaX) > d_maxSize.d_width) {
00296                 deltaX = d_maxSize.d_width - width;
00297         }
00298 
00299         // update window state
00300         d_abs_area.d_right += deltaX;
00301         d_dragPoint.d_x += deltaX;
00302 
00303         d_rel_area.d_right = absoluteToRelativeX_impl(getParent(), d_abs_area.d_right);
00304 
00305         WindowEventArgs args(this);
00306         onSized(args);
00307         onSegmentSized(args);
00308 }
00309 
00310 
00311 /*************************************************************************
00312         Processing for drag-moving the segment
00313 *************************************************************************/
00314 void ListHeaderSegment::doDragMoving(const Point& local_mouse)
00315 {
00316         // calculate movement deltas.
00317         float   deltaX = local_mouse.d_x - d_dragPoint.d_x;
00318         float   deltaY = local_mouse.d_y - d_dragPoint.d_y;
00319 
00320         // update 'ghost' position
00321         d_dragPosition.d_x += deltaX;
00322         d_dragPosition.d_y += deltaY;
00323 
00324         // update drag point.
00325         d_dragPoint.d_x += deltaX;
00326         d_dragPoint.d_y += deltaY;
00327 
00328         WindowEventArgs args(this);
00329         onSegmentDragPositionChanged(args);
00330 }
00331 
00332 
00333 /*************************************************************************
00334         Initialise and enter the drag moving state.
00335 *************************************************************************/
00336 void ListHeaderSegment::initDragMoving(void)
00337 {
00338         if (d_movingEnabled)
00339         {
00340                 // initialise drag moving state
00341                 d_dragMoving = true;
00342                 d_segmentPushed = false;
00343                 d_segmentHover = false;
00344                 d_dragPosition.d_x = 0.0f;
00345                 d_dragPosition.d_y = 0.0f;
00346 
00347                 // setup new cursor
00348                 MouseCursor::getSingleton().setImage(d_movingMouseCursor);
00349 
00350                 // Trigger the event
00351                 WindowEventArgs args(this);
00352                 onSegmentDragStart(args);
00353         }
00354 
00355 }
00356 
00357 
00358 /*************************************************************************
00359         Initialise the state for hovering over sizing area.
00360 *************************************************************************/
00361 void ListHeaderSegment::initSizingHoverState(void)
00362 {
00363         // only react if settings are changing.
00364         if (!d_splitterHover  && !d_segmentPushed)
00365         {
00366                 d_splitterHover = true;
00367 
00368                 // change the mouse cursor.
00369                 MouseCursor::getSingleton().setImage(d_sizingMouseCursor);
00370 
00371                 // trigger redraw so 'sizing' area can be highlighted if needed.
00372                 requestRedraw();
00373         }
00374 
00375         // reset segment hover as needed.
00376         if (d_segmentHover)
00377         {       
00378                 d_segmentHover = false;
00379                 requestRedraw();
00380         }
00381 
00382 }
00383 
00384 
00385 /*************************************************************************
00386         Initialise the state for hovering over main segment area
00387 *************************************************************************/
00388 void ListHeaderSegment::initSegmentHoverState(void)
00389 {
00390         // reset sizing area hover state if needed.
00391         if (d_splitterHover)
00392         {
00393                 d_splitterHover = false;
00394                 MouseCursor::getSingleton().setImage(d_normalMouseCursor);
00395                 requestRedraw();
00396         }
00397 
00398         // set segment hover state if not already set.
00399         if ((!d_segmentHover) && isClickable())
00400         {
00401                 d_segmentHover = true;
00402                 requestRedraw();
00403         }
00404 }
00405 
00406 
00407 /*************************************************************************
00408         Return true if move threshold for initiating drag-moving has been
00409         exceeded.
00410 *************************************************************************/
00411 bool ListHeaderSegment::isDragMoveThresholdExceeded(const Point& local_mouse)
00412 {
00413         // see if mouse has moved far enough to start move operation
00414         // calculate movement deltas.
00415         float   deltaX = local_mouse.d_x - d_dragPoint.d_x;
00416         float   deltaY = local_mouse.d_y - d_dragPoint.d_y;
00417 
00418         if ((deltaX > SegmentMoveThreshold) || (deltaX < -SegmentMoveThreshold) ||
00419                 (deltaY > SegmentMoveThreshold) || (deltaY < -SegmentMoveThreshold))
00420         {
00421                 return true;
00422         }
00423         else
00424         {
00425                 return false;
00426         }
00427 
00428 }
00429 
00430 
00431 /*************************************************************************
00432         Handler for when mouse position changes in widget area (or captured)
00433 *************************************************************************/
00434 void ListHeaderSegment::onMouseMove(MouseEventArgs& e)
00435 {
00436         // base class processing
00437         Window::onMouseMove(e);
00438 
00439         //
00440         // convert mouse position to something local
00441         //
00442         Point localMousePos(screenToWindow(e.position));
00443 
00444         if (getMetricsMode() == Relative)
00445         {
00446                 localMousePos = relativeToAbsolute(localMousePos);
00447         }
00448 
00449         // handle drag sizing
00450         if (d_dragSizing)
00451         {
00452                 doDragSizing(localMousePos);
00453         }
00454         // handle drag moving
00455         else if (d_dragMoving)
00456         {
00457                 doDragMoving(localMousePos);
00458         }
00459         // not sizing, is mouse in the widget area?
00460         else if (isHit(e.position))
00461         {
00462                 // mouse in sizing area & sizing is enabled
00463                 if ((localMousePos.d_x > (getAbsoluteWidth() - d_splitterSize)) && d_sizingEnabled)
00464                 {
00465                         initSizingHoverState();
00466                 }
00467                 // mouse not in sizing area and/or sizing not enabled
00468                 else
00469                 {
00470                         initSegmentHoverState();
00471 
00472                         // if we are pushed but not yet drag moving
00473                         if (d_segmentPushed && !d_dragMoving)
00474                         {
00475                                 if (isDragMoveThresholdExceeded(localMousePos))
00476                                 {
00477                                         initDragMoving();
00478                                 }
00479 
00480                         }
00481 
00482                 }
00483 
00484         }
00485         // mouse is no longer within the widget area...
00486         else
00487         {
00488                 // only change settings if change is required
00489                 if (d_splitterHover)
00490                 {
00491                         d_splitterHover = false;
00492                         MouseCursor::getSingleton().setImage(d_normalMouseCursor);
00493                         requestRedraw();
00494                 }
00495 
00496                 // reset segment hover state if not already done.
00497                 if (d_segmentHover)
00498                 {       
00499                         d_segmentHover = false;
00500                         requestRedraw();
00501                 }
00502 
00503         }
00504 
00505         e.handled = true;
00506 }
00507 
00508 
00509 /*************************************************************************
00510         Handler for when mouse buttons are pushed
00511 *************************************************************************/
00512 void ListHeaderSegment::onMouseButtonDown(MouseEventArgs& e)
00513 {
00514         // base class processing
00515         Window::onMouseButtonDown(e);
00516 
00517         if (e.button == LeftButton)
00518         {
00519                 // ensure all inputs come to us for now
00520                 if (captureInput())
00521                 {
00522                         // get position of mouse as co-ordinates local to this window.
00523                         Point localPos(screenToWindow(e.position));
00524 
00525                         if (getMetricsMode() == Relative)
00526                         {
00527                                 localPos = relativeToAbsolute(localPos);
00528                         }
00529 
00530                         // store drag point for possible sizing or moving operation.
00531                         d_dragPoint = localPos;
00532 
00533                         // if the mouse is in the sizing area
00534                         if (d_splitterHover)
00535                         {
00536                                 if (isSizingEnabled())
00537                                 {
00538                                         // setup the 'dragging' state variables
00539                                         d_dragSizing = true;
00540                                 }
00541 
00542                         }
00543                         else
00544                         {
00545                                 d_segmentPushed = true;
00546                         }
00547 
00548                 }
00549 
00550                 e.handled = true;
00551         }
00552 
00553 }
00554 
00555 
00556 /*************************************************************************
00557         Handler for when mouse buttons area released
00558 *************************************************************************/
00559 void ListHeaderSegment::onMouseButtonUp(MouseEventArgs& e)
00560 {
00561         // base class processing
00562         Window::onMouseButtonUp(e);
00563 
00564         if (e.button == LeftButton)
00565         {
00566                 // if we were pushed and mouse was released within our segment area
00567                 if (d_segmentPushed && d_segmentHover)
00568                 {
00569                         WindowEventArgs args(this);
00570                         onSegmentClicked(args);
00571                 }
00572                 else if (d_dragMoving)
00573                 {
00574                         MouseCursor::getSingleton().setImage(d_normalMouseCursor);
00575                         
00576                         WindowEventArgs args(this);
00577                         onSegmentDragStop(args);
00578                 }
00579 
00580                 // release our capture on the input data
00581                 releaseInput();
00582                 e.handled = true;
00583         }
00584 
00585 }
00586 
00587 
00588 /*************************************************************************
00589         Handler for when a mouse button is double-clicked
00590 *************************************************************************/
00591 void ListHeaderSegment::onMouseDoubleClicked(MouseEventArgs& e)
00592 {
00593         // base class processing
00594         Window::onMouseDoubleClicked(e);
00595 
00596         // if double-clicked on splitter / sizing area
00597         if ((e.button == LeftButton) && d_splitterHover)
00598         {
00599                 WindowEventArgs args(this);
00600                 onSplitterDoubleClicked(args);
00601 
00602                 e.handled = true;
00603         }
00604 
00605 }
00606 
00607 
00608 /*************************************************************************
00609         Handler for when mouse leaves the widget area (uncaptured)
00610 *************************************************************************/
00611 void ListHeaderSegment::onMouseLeaves(MouseEventArgs& e)
00612 {
00613         // base class processing
00614         Window::onMouseLeaves(e);
00615 
00616         d_splitterHover = false;
00617         d_dragSizing = false;
00618         d_segmentHover = false;
00619         requestRedraw();
00620 }
00621 
00622 
00623 /*************************************************************************
00624         Handler for when mouse input capture is lost
00625 *************************************************************************/
00626 void ListHeaderSegment::onCaptureLost(WindowEventArgs& e)
00627 {
00628         // base class processing
00629         Window::onCaptureLost(e);
00630 
00631         // reset segment state
00632         d_dragSizing = false;
00633         d_segmentPushed = false;
00634         d_dragMoving = false;
00635 
00636         e.handled = true;
00637 }
00638 
00639 /*************************************************************************
00640         adds properties for the class
00641 *************************************************************************/
00642 void ListHeaderSegment::addHeaderSegmentProperties(void)
00643 {
00644         addProperty(&d_clickableProperty);
00645         addProperty(&d_sizableProperty);
00646         addProperty(&d_dragableProperty);
00647         addProperty(&d_sortDirectionProperty);
00648 }
00649 
00650 
00651 
00652 } // End of  CEGUI namespace section

Generated on Wed Feb 16 12:41:06 2005 for Crazy Eddies GUI System by  doxygen 1.3.9.1