|
From: CVS C. to T. <the...@li...> - 2015-06-06 22:09:59
|
Revision: 726
http://sourceforge.net/p/themis/code/726
Author: mark_hellegers
Date: 2015-06-06 22:09:56 +0000 (Sat, 06 Jun 2015)
Log Message:
-----------
Move table code to common directory, so it can be reused.
Modified Paths:
--------------
trunk/themis/makefile
Added Paths:
-----------
trunk/themis/common/ColorTools.cpp
trunk/themis/common/ColorTools.h
trunk/themis/common/ColumnListView.cpp
trunk/themis/common/ColumnListView.h
trunk/themis/common/ColumnTypes.cpp
trunk/themis/common/ColumnTypes.h
trunk/themis/common/ObjectList.h
Removed Paths:
-------------
trunk/themis/modules/CSSViewer/ColorTools.cpp
trunk/themis/modules/CSSViewer/ColorTools.h
trunk/themis/modules/CSSViewer/ColumnListView.cpp
trunk/themis/modules/CSSViewer/ColumnListView.h
trunk/themis/modules/CSSViewer/ColumnTypes.cpp
trunk/themis/modules/CSSViewer/ColumnTypes.h
trunk/themis/modules/CSSViewer/ObjectList.h
Copied: trunk/themis/common/ColorTools.cpp (from rev 719, trunk/themis/modules/CSSViewer/ColorTools.cpp)
===================================================================
--- trunk/themis/common/ColorTools.cpp (rev 0)
+++ trunk/themis/common/ColorTools.cpp 2015-06-06 22:09:56 UTC (rev 726)
@@ -0,0 +1,110 @@
+/*
+Open Tracker License
+
+Terms and Conditions
+
+Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice applies to all licensees
+and shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Be Incorporated shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+this Software without prior written authorization from Be Incorporated.
+
+Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
+of Be Incorporated in the United States and other countries. Other brand product
+names are registered trademarks or trademarks of their respective holders.
+All rights reserved.
+*/
+
+/*******************************************************************************
+/
+/ File: ColorTools.cpp
+/
+/ Description: Additional experimental color manipulation functions.
+/
+/ Copyright 2000, Be Incorporated, All Rights Reserved
+/
+*******************************************************************************/
+
+#include "ColorTools.h"
+
+#if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI
+
+namespace BExperimental {
+
+#if DEBUG
+#define DB_INLINE
+#else
+#define DB_INLINE inline
+#endif
+
+static DB_INLINE void mix_color_func(rgb_color* target, const rgb_color other, uint8 amount)
+{
+ target->red = (uint8)( ((int16(other.red)-int16(target->red))*amount)/255
+ + target->red );
+ target->green = (uint8)( ((int16(other.green)-int16(target->green))*amount)/255
+ + target->green );
+ target->blue = (uint8)( ((int16(other.blue)-int16(target->blue))*amount)/255
+ + target->blue );
+ target->alpha = (uint8)( ((int16(other.alpha)-int16(target->alpha))*amount)/255
+ + target->alpha );
+}
+
+static DB_INLINE void blend_color_func(rgb_color* target, const rgb_color other, uint8 amount)
+{
+ const uint8 alphaMix = (uint8)( ((int16(other.alpha)-int16(255-target->alpha))*amount)/255
+ + (255-target->alpha) );
+ target->red = (uint8)( ((int16(other.red)-int16(target->red))*alphaMix)/255
+ + target->red );
+ target->green = (uint8)( ((int16(other.green)-int16(target->green))*alphaMix)/255
+ + target->green );
+ target->blue = (uint8)( ((int16(other.blue)-int16(target->blue))*alphaMix)/255
+ + target->blue );
+ target->alpha = (uint8)( ((int16(other.alpha)-int16(target->alpha))*amount)/255
+ + target->alpha );
+}
+
+static DB_INLINE void disable_color_func(rgb_color* target, const rgb_color background)
+{
+ blend_color_func(target, background, 255-70);
+}
+
+// --------------------------------------------------------------------------
+
+rgb_color mix_color(rgb_color color1, rgb_color color2, uint8 amount)
+{
+ mix_color_func(&color1, color2, amount);
+ return color1;
+}
+
+rgb_color blend_color(rgb_color color1, rgb_color color2, uint8 amount)
+{
+ blend_color_func(&color1, color2, amount);
+ return color1;
+}
+
+rgb_color disable_color(rgb_color color, rgb_color background)
+{
+ disable_color_func(&color, background);
+ return color;
+}
+
+}
+
+#endif
Copied: trunk/themis/common/ColorTools.h (from rev 719, trunk/themis/modules/CSSViewer/ColorTools.h)
===================================================================
--- trunk/themis/common/ColorTools.h (rev 0)
+++ trunk/themis/common/ColorTools.h 2015-06-06 22:09:56 UTC (rev 726)
@@ -0,0 +1,105 @@
+/*
+Open Tracker License
+
+Terms and Conditions
+
+Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice applies to all licensees
+and shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Be Incorporated shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+this Software without prior written authorization from Be Incorporated.
+
+Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
+of Be Incorporated in the United States and other countries. Other brand product
+names are registered trademarks or trademarks of their respective holders.
+All rights reserved.
+*/
+
+/*******************************************************************************
+/
+/ File: ColorTools.h
+/
+/ Description: Additional experimental color manipulation functions.
+/
+/ Copyright 2000, Be Incorporated, All Rights Reserved
+/
+*******************************************************************************/
+
+
+#ifndef _COLOR_TOOLS_H
+#define _COLOR_TOOLS_H
+
+#include <GraphicsDefs.h>
+
+#if B_BEOS_VERSION <= B_BEOS_VERSION_5
+
+namespace BExperimental {
+
+// Comparison operators.
+
+inline bool operator==(const rgb_color c1, const rgb_color c2)
+{
+ return (*((uint32*)&c1)) == (*((uint32*)&c2));
+}
+
+inline bool operator!=(const rgb_color c1, const rgb_color c2)
+{
+ return (*((uint32*)&c1)) != (*((uint32*)&c2));
+}
+
+#ifndef __HAIKU__
+// Color creation.
+
+inline rgb_color make_color(uint8 red, uint8 green, uint8 blue, uint8 alpha=255)
+{
+ rgb_color c;
+ c.red = red;
+ c.green = green;
+ c.blue = blue;
+ c.alpha = alpha;
+ return c;
+}
+#endif
+
+// Mix two colors together, ignoring their relative alpha channels.
+// If amount is 0, the result is color1; if 255, the result is color2;
+// if another value, it is somewhere in-between. The resulting alpha
+// channel is mixed exactly like the other color channels.
+rgb_color mix_color(rgb_color color1, rgb_color color2, uint8 amount);
+
+// Blend two colors together, weighting by their relative alpha channels.
+// The resulting color is the same as mix_color(), except that the amount
+// used from color1 and color2's color channels is dependent on that color's
+// alpha channel. For example, if color1.alpha is 0 and color2.alpha is
+// 255, the resulting red, green, and blue values will be the same as those
+// in color2, regardless of 'amount'.
+rgb_color blend_color(rgb_color color1, rgb_color color2, uint8 amount);
+
+// Return a color that is the disabled representation of 'color' when drawn
+// on a solid color 'background'.
+rgb_color disable_color(rgb_color color, rgb_color background);
+
+} // namespace BExperimental
+
+using namespace BExperimental;
+
+#endif
+
+#endif
Copied: trunk/themis/common/ColumnListView.cpp (from rev 719, trunk/themis/modules/CSSViewer/ColumnListView.cpp)
===================================================================
--- trunk/themis/common/ColumnListView.cpp (rev 0)
+++ trunk/themis/common/ColumnListView.cpp 2015-06-06 22:09:56 UTC (rev 726)
@@ -0,0 +1,4196 @@
+/*
+Open Tracker License
+
+Terms and Conditions
+
+Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice applies to all licensees
+and shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Be Incorporated shall not be
+used in advertising or otherwise to promote the sale, use or other dealings in
+this Software without prior written authorization from Be Incorporated.
+
+Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
+of Be Incorporated in the United States and other countries. Other brand product
+names are registered trademarks or trademarks of their respective holders.
+All rights reserved.
+*/
+
+/*******************************************************************************
+/
+/ File: ColumnListView.cpp
+/
+/ Description: Experimental multi-column list view.
+/
+/ Copyright 2000+, Be Incorporated, All Rights Reserved
+/ By Jeff Bush
+/
+*******************************************************************************/
+
+#include <typeinfo>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <Application.h>
+#include <Bitmap.h>
+#if _INCLUDES_CLASS_CURSOR
+#include <Cursor.h>
+#endif
+#include <Debug.h>
+#include <GraphicsDefs.h>
+#include <MenuItem.h>
+#include <PopUpMenu.h>
+#include <Region.h>
+#include <ScrollBar.h>
+#include <String.h>
+#include <Window.h>
+
+#include "ObjectList.h"
+#include "ColumnListView.h"
+#include "ColorTools.h"
+/*
+#ifndef _ARCHIVE_DEFS_H
+#include <archive_defs.h>
+#endif
+*/
+#define DOUBLE_BUFFERED_COLUMN_RESIZE 1
+#define SMART_REDRAW 1
+#define DRAG_TITLE_OUTLINE 1
+#define CONSTRAIN_CLIPPING_REGION 1
+#define LOWER_SCROLLBAR 1
+
+namespace BPrivate {
+
+static const unsigned char kResizeCursorData[] = {
+ 16, 1, 8, 8,
+ 0, 0, 1, 0x80, 1, 0x80, 1, 0x80, 9, 0x90, 0x19, 0x98, 0x39, 0x09c, 0x79, 0x9e,
+ 0x79, 0x9e, 0x39, 0x9c, 0x19, 0x98, 0x9, 0x90, 1, 0x80, 1, 0x80, 1, 0x80, 0, 0,
+ 3, 0xc0, 3, 0xc0, 3, 0xc0, 0xf, 0xf0, 0x1f, 0xf8, 0x3f, 0xfa, 0x7f, 0xfe, 0xff, 0xff,
+ 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfa, 0x1f, 0xf8, 0xf, 0xf0, 3, 0xc0, 3, 0xc0, 3, 0xc0
+};
+
+static const unsigned char kMaxResizeCursorData[] = {
+ 16, 1, 8, 8,
+ 0, 0, 1, 0x80, 1, 0x80, 1, 0x80, 9, 0x80, 0x19, 0x80, 0x39, 0x80, 0x79, 0x80,
+ 0x79, 0x80, 0x39, 0x80, 0x19, 0x80, 0x9, 0x80, 1, 0x80, 1, 0x80, 1, 0x80, 0, 0,
+ 3, 0xc0, 3, 0xc0, 3, 0xc0, 0xf, 0xc0, 0x1f, 0xc0, 0x3f, 0xc0, 0x7f, 0xc0, 0xff, 0xc0,
+ 0xff, 0xc0, 0x7f, 0xc0, 0x3f, 0xc0, 0x1f, 0xc0, 0xf, 0xc0, 3, 0xc0, 3, 0xc0, 3, 0xc0
+};
+
+static const unsigned char kMinResizeCursorData[] = {
+ 16, 1, 8, 8,
+ 0, 0, 1, 0x80, 1, 0x80, 1, 0x80, 1, 0x90, 1, 0x98, 1, 0x09c, 1, 0x9e,
+ 1, 0x9e, 1, 0x9c, 1, 0x98, 1, 0x90, 1, 0x80, 1, 0x80, 1, 0x80, 0, 0,
+ 3, 0xc0, 3, 0xc0, 3, 0xc0, 3, 0xf0, 3, 0xf8, 3, 0xfa, 3, 0xfe, 3, 0xff,
+ 3, 0xff, 3, 0xfe, 3, 0xfa, 3, 0xf8, 3, 0xf0, 3, 0xc0, 3, 0xc0, 3, 0xc0
+};
+
+static const unsigned char kColumnMoveCursorData[] = {
+ 16, 1, 8, 8,
+ 1, 0x80, 3, 0xc0, 7, 0xe0, 0, 0, 0, 0, 0x20, 4, 0x61, 0x86, 0xe3, 0xc7,
+ 0xe3, 0xc7, 0x61, 0x86, 0x20, 4, 0, 0, 0, 0, 7, 0xe0, 3, 0xc0, 1, 0x80,
+ 1, 0x80, 3, 0xc0, 7, 0xe0, 0, 0, 0, 0, 0x20, 4, 0x61, 0x86, 0xe3, 0xc7,
+ 0xe3, 0xc7, 0x61, 0x86, 0x20, 4, 0, 0, 0, 0, 7, 0xe0, 3, 0xc0, 1, 0x80
+};
+
+static const unsigned char kUpSortArrow8x8[] = {
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff
+};
+
+static const unsigned char kDownSortArrow8x8[] = {
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff
+};
+
+static const unsigned char kUpSortArrow8x8Invert[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff
+};
+
+static const unsigned char kDownSortArrow8x8Invert[] = {
+ 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+/*
+static const rgb_color kTitleColor = {215, 215, 215, 255};
+static const rgb_color kTitleTextColor = { 0, 0, 0, 255 };
+static const rgb_color kDefaultBackgroundColor = {236, 236, 236, 255};
+static const rgb_color kRowDividerColor = {148, 148, 148, 255};
+static const rgb_color kDefaultSelectionColor = {255, 255, 255, 255};
+static const rgb_color kDefaultEditColor = {180, 180, 180, 180};
+static const rgb_color kNonFocusSelectionColor = {220, 220, 220, 255};
+*/
+
+static const float kTitleHeight = 17.0;
+static const float kLatchWidth = 15.0;
+
+
+static const rgb_color kColor[B_COLOR_TOTAL] =
+{
+ {236, 236, 236, 255}, // B_COLOR_BACKGROUND
+ { 0, 0, 0, 255}, // B_COLOR_TEXT
+ {148, 148, 148, 255}, // B_COLOR_ROW_DIVIDER
+ {255, 255, 255, 255}, // B_COLOR_SELECTION
+ { 0, 0, 0, 255}, // B_COLOR_SELECTION_TEXT
+ {220, 220, 220, 255}, // B_COLOR_NON_FOCUS_SELECTION
+ {180, 180, 180, 180}, // B_COLOR_EDIT_BACKGROUND
+ { 0, 0, 0, 255}, // B_COLOR_EDIT_TEXT
+ {215, 215, 215, 255}, // B_COLOR_HEADER_BACKGROUND
+ { 0, 0, 0, 255}, // B_COLOR_HEADER_TEXT
+ { 0, 0, 0, 255}, // B_COLOR_SEPARATOR_LINE
+ { 0, 0, 0, 255}, // B_COLOR_SEPARATOR_BORDER
+};
+
+static const int32 kMaxDepth = 1024;
+static const float kLeftMargin = kLatchWidth;
+static const float kRightMargin = kLatchWidth;
+static const float kBottomMargin = kLatchWidth;
+static const float kOutlineLevelIndent = kLatchWidth;
+static const float kColumnResizeAreaWidth = 10.0;
+static const float kRowDragSensitivity = 5.0;
+static const float kDoubleClickMoveSensitivity = 4.0;
+static const float kSortIndicatorWidth = 9.0;
+static const float kDropHighlightLineHeight = 2.0;
+
+static const uint32 kToggleColumn = 'BTCL';
+
+class BRowContainer : public BObjectList<BRow>
+{
+};
+
+class TitleView : public BView {
+public:
+ TitleView(BRect, OutlineView*, BList *visibleColumns, BList *sortColumns,
+ BColumnListView *masterView, uint32 resizingMode);
+ ~TitleView();
+ void ColumnAdded(BColumn*);
+ void SetColumnVisible(BColumn*, bool);
+
+ virtual void Draw(BRect rect);
+ virtual void ScrollTo(BPoint);
+ virtual void MessageReceived(BMessage*);
+ virtual void MouseDown(BPoint);
+ virtual void MouseMoved(BPoint, uint32, const BMessage*);
+ virtual void MouseUp(BPoint position);
+ virtual void FrameResized(float width, float height);
+
+ void MoveColumn(BColumn *column, int32 index);
+ void SetColumnFlags(column_flags flags);
+
+ void SetEditMode(bool state) { fEditMode = state; }
+
+private:
+ void GetTitleRect(BColumn*, BRect *out_rect);
+ int32 FindColumn(BPoint, float *out_leftEdge);
+ void FixScrollBar(bool scrollToFit);
+ void DragSelectedColumn(BPoint);
+ void ResizeSelectedColumn(BPoint);
+ void ComputeDragBoundries(BColumn*, BPoint);
+ void DrawTitle(BView*, BRect, BColumn*, bool depressed);
+
+ OutlineView *fOutlineView;
+ BList *fColumns;
+ BList *fSortColumns;
+ float fColumnsWidth;
+ BRect fVisibleRect;
+
+#if DOUBLE_BUFFERED_COLUMN_RESIZE
+ BBitmap *fDrawBuffer;
+ BView *fDrawBufferView;
+#endif
+
+ enum {
+ INACTIVE,
+ RESIZING_COLUMN,
+ PRESSING_COLUMN,
+ DRAG_COLUMN_INSIDE_TITLE,
+ DRAG_COLUMN_OUTSIDE_TITLE
+ } fCurrentState;
+
+ BPopUpMenu *fColumnPop;
+ BColumnListView *fMasterView;
+ bool fEditMode;
+ int32 fColumnFlags;
+
+ // State information for resizing/dragging
+ BColumn *fSelectedColumn;
+ BRect fSelectedColumnRect;
+ bool fResizingFirstColumn;
+ BPoint fClickPoint; // offset within cell
+ float fLeftDragBoundry;
+ float fRightDragBoundry;
+ BPoint fCurrentDragPosition;
+
+
+ BBitmap *fUpSortArrow;
+ BBitmap *fDownSortArrow;
+#if _INCLUDES_CLASS_CURSOR
+ BCursor *fResizeCursor;
+ BCursor *fMinResizeCursor;
+ BCursor *fMaxResizeCursor;
+ BCursor *fColumnMoveCursor;
+#endif
+
+
+ typedef BView _inherited;
+};
+
+class OutlineView : public BView {
+public:
+ OutlineView(BRect, BList *visibleColumns, BList *sortColumns, BColumnListView *listView);
+ ~OutlineView();
+
+ virtual void Draw(BRect);
+ const BRect& VisibleRect() const;
+
+ void RedrawColumn(BColumn *column, float leftEdge, bool isFirstColumn);
+ void StartSorting();
+
+ void AddRow(BRow*, int32 index, BRow *TheRow);
+ BRow* CurrentSelection(BRow *lastSelected) const;
+ void ToggleFocusRowSelection(bool selectRange);
+ void ToggleFocusRowOpen();
+ void ChangeFocusRow(bool up, bool updateSelection, bool addToCurrentSelection);
+ void MoveFocusToVisibleRect();
+ void ExpandOrCollapse(BRow *parent, bool expand);
+ void RemoveRow(BRow*);
+ BRowContainer* RowList();
+ void UpdateRow(BRow*);
+ bool FindParent(BRow *row, BRow **out_parent, bool *out_isVisible);
+ int32 IndexOf(BRow *row);
+ void Deselect(BRow*);
+ void AddToSelection(BRow*);
+ void DeselectAll();
+ BRow* FocusRow() const;
+ void SetFocusRow(BRow *row, bool select);
+ BRow* FindRow(float ypos, int32 *out_indent, float *out_top);
+ bool FindRect(const BRow *row, BRect *out_rect);
+ void ScrollTo(const BRow* Row);
+
+ void Clear();
+ void SetSelectionMode(list_view_type);
+ list_view_type SelectionMode() const;
+ void SetMouseTrackingEnabled(bool);
+ void FixScrollBar(bool scrollToFit);
+ void SetEditMode(bool state) { fEditMode = state; }
+
+ virtual void FrameResized(float width, float height);
+ virtual void ScrollTo(BPoint pt);
+ virtual void MouseDown(BPoint);
+ virtual void MouseMoved(BPoint, uint32, const BMessage*);
+ virtual void MouseUp(BPoint);
+ virtual void MessageReceived(BMessage*);
+
+private:
+ bool SortList(BRowContainer *list, bool isVisible);
+ static int32 DeepSortThreadEntry(void *outlineView);
+ void DeepSort();
+ void SelectRange(BRow *start, BRow *end);
+ int32 CompareRows(BRow *row1, BRow *row2);
+ void AddSorted(BRowContainer *list, BRow *row);
+ void RecursiveDeleteRows(BRowContainer *list, bool owner);
+ void InvalidateCachedPositions();
+ bool FindVisibleRect(BRow *row, BRect *out_rect);
+
+ BList* fColumns;
+ BList* fSortColumns;
+ float fItemsHeight;
+ BRowContainer fRows;
+ BRect fVisibleRect;
+
+#if DOUBLE_BUFFERED_COLUMN_RESIZE
+ BBitmap* fDrawBuffer;
+ BView* fDrawBufferView;
+#endif
+
+ BRow* fFocusRow;
+ BRect fFocusRowRect;
+ BRow* fRollOverRow;
+
+ BRow fSelectionListDummyHead;
+ BRow* fLastSelectedItem;
+ BRow* fFirstSelectedItem;
+
+ thread_id fSortThread;
+ int32 fNumSorted;
+ bool fSortCancelled;
+
+ enum CurrentState
+ {
+ INACTIVE,
+ LATCH_CLICKED,
+ ROW_CLICKED,
+ DRAGGING_ROWS
+ };
+
+ CurrentState fCurrentState;
+
+
+ BColumnListView* fMasterView;
+ list_view_type fSelectionMode;
+ bool fTrackMouse;
+ BField* fCurrentField;
+ BRow* fCurrentRow;
+ BColumn* fCurrentColumn;
+ bool fMouseDown;
+ BRect fFieldRect;
+ int32 fCurrentCode;
+ bool fEditMode;
+
+ // State information for mouse/keyboard interaction
+ BPoint fClickPoint;
+ bool fDragging;
+ int32 fClickCount;
+ BRow *fTargetRow;
+ float fTargetRowTop;
+ BRect fLatchRect;
+ float fDropHighlightY;
+
+ friend class RecursiveOutlineIterator;
+ typedef BView _inherited;
+};
+
+class RecursiveOutlineIterator {
+public:
+ RecursiveOutlineIterator(BRowContainer*, bool openBranchesOnly = true);
+ BRow *CurrentRow() const;
+ int32 CurrentLevel() const;
+ void GoToNext();
+
+private:
+ struct {
+ BRowContainer *fRowSet;
+ int32 fIndex;
+ int32 fDepth;
+ } fStack[kMaxDepth];
+
+ int32 fStackIndex;
+ BRowContainer *fCurrentList;
+ int32 fCurrentListIndex;
+ int32 fCurrentListDepth;
+ bool fOpenBranchesOnly;
+};
+
+} // namespace BPrivate
+
+using namespace BPrivate;
+
+BField::BField()
+{
+}
+
+BField::~BField()
+{
+}
+
+// #pragma mark -
+
+void BColumn::MouseMoved(BColumnListView */*parent*/, BRow */*row*/, BField */*field*/,
+ BRect /*field_rect*/, BPoint/*point*/, uint32 /*buttons*/, int32 /*code*/)
+{
+}
+
+void BColumn::MouseDown( BColumnListView */*parent*/, BRow */*row*/, BField */*field*/,
+ BRect /*field_rect*/, BPoint /*point*/, uint32 /*buttons*/)
+{
+}
+
+void BColumn::MouseUp(BColumnListView */*parent*/, BRow */*row*/, BField */*field*/)
+{
+}
+
+// #pragma mark -
+
+BRow::BRow(float height)
+ : fChildList(NULL),
+ fIsExpanded(false),
+ fHeight(height),
+ fNextSelected(NULL),
+ fPrevSelected(NULL),
+ fParent(NULL),
+ fList(NULL)
+{
+}
+
+BRow::~BRow()
+{
+ while (true) {
+ BField *field = (BField*) fFields.RemoveItem(0L);
+ if (field == 0)
+ break;
+
+ delete field;
+ }
+}
+
+bool BRow::HasLatch() const
+{
+ return fChildList != 0;
+}
+
+int32 BRow::CountFields() const
+{
+ return fFields.CountItems();
+}
+
+BField* BRow::GetField(int32 index)
+{
+ return (BField*) fFields.ItemAt(index);
+}
+
+const BField* BRow::GetField(int32 index) const
+{
+ return (const BField*) fFields.ItemAt(index);
+}
+
+void BRow::SetField(BField *field, int32 logicalFieldIndex)
+{
+ if (fFields.ItemAt(logicalFieldIndex) != 0)
+ delete (BField*) fFields.RemoveItem(logicalFieldIndex);
+
+ if( NULL != fList ) {
+ ValidateField(field, logicalFieldIndex);
+ BRect inv;
+ fList->GetRowRect(this, &inv);
+ fList->Invalidate(inv);
+ }
+
+ fFields.AddItem(field, logicalFieldIndex);
+}
+
+float BRow::Height() const
+{
+ return fHeight;
+}
+
+bool BRow::IsExpanded() const
+{
+ return fIsExpanded;
+}
+
+void
+BRow::ValidateFields() const
+{
+ for( int32 i = 0; i < CountFields(); i++ )
+ {
+ ValidateField(GetField(i), i);
+ }
+}
+
+void
+BRow::ValidateField(const BField *field, int32 logicalFieldIndex) const
+{
+ // The Fields may be moved by the user, but the logicalFieldIndexes
+ // do not change, so we need to map them over when checking the
+ // Field types.
+ BColumn* col = NULL;
+ int32 items = fList->CountColumns();
+ for( int32 i = 0 ; i < items; ++i )
+ {
+ col = fList->ColumnAt(i);
+ if( col->LogicalFieldNum() == logicalFieldIndex )
+ break;
+ }
+
+ if( NULL == col )
+ {
+ BString dbmessage("\n\n\tThe parent BColumnListView does not have "
+ "\n\ta BColumn at the logical field index ");
+ dbmessage << logicalFieldIndex << ".\n\n";
+ printf(dbmessage.String());
+ }
+ else
+ {
+ if( false == col->AcceptsField(field) )
+ {
+ BString dbmessage("\n\n\tThe BColumn of type ");
+ dbmessage << typeid(*col).name() << "\n\tat logical field index "
+ << logicalFieldIndex << "\n\tdoes not support the field type "
+ << typeid(*field).name() << ".\n\n";
+ debugger(dbmessage.String());
+ }
+ }
+}
+
+
+// #pragma mark -
+
+BColumn::BColumn(float width, float minWidth, float maxWidth, alignment align)
+ : fWidth(width),
+ fMinWidth(minWidth),
+ fMaxWidth(maxWidth),
+ fVisible(true),
+ fList(0),
+ fShowHeading(true),
+ fAlignment(align)
+{
+}
+
+BColumn::~BColumn()
+{
+}
+
+float BColumn::Width() const
+{
+ return fWidth;
+}
+
+void BColumn::SetWidth(float width)
+{
+ fWidth = width;
+}
+
+float BColumn::MinWidth() const
+{
+ return fMinWidth;
+}
+
+float BColumn::MaxWidth() const
+{
+ return fMaxWidth;
+}
+
+void BColumn::DrawTitle(BRect, BView*)
+{
+}
+
+void BColumn::DrawField(BField*, BRect, BView*)
+{
+}
+
+int BColumn::CompareFields(BField *, BField *)
+{
+ return 0;
+}
+
+void BColumn::GetColumnName(BString* into) const
+{
+ *into = "(Unnamed)";
+}
+
+float BColumn::GetPreferredWidth(BField *field, BView *parent) const
+{
+ return 0;
+}
+
+bool BColumn::IsVisible() const
+{
+ return fVisible;
+}
+
+void BColumn::SetVisible(bool visible)
+{
+ if (fList && (fVisible != visible))
+ fList->SetColumnVisible(this, visible);
+}
+
+bool BColumn::ShowHeading() const
+{
+ return fShowHeading;
+}
+
+void BColumn::SetShowHeading(bool state)
+{
+ fShowHeading = state;
+}
+
+alignment BColumn::Alignment() const
+{
+ return fAlignment;
+}
+
+void BColumn::SetAlignment(alignment align)
+{
+ fAlignment = align;
+}
+
+bool BColumn::WantsEvents() const
+{
+ return fWantsEvents;
+}
+
+void BColumn::SetWantsEvents(bool state)
+{
+ fWantsEvents = state;
+}
+
+int32 BColumn::LogicalFieldNum() const
+{
+ return fFieldID;
+}
+
+bool
+BColumn::AcceptsField(const BField*) const
+{
+ return true;
+}
+
+
+// #pragma mark -
+
+BColumnListView::BColumnListView(BRect rect, const char *name, uint32 resizingMode,
+ uint32 drawFlags, border_style border, bool showHorizontalScrollbar)
+ : BView(rect, name, resizingMode, drawFlags | B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE),
+ fStatusView(0),
+ fSelectionMessage(0),
+ fSortingEnabled(true),
+ fLatchWidth(kLatchWidth),
+ fBorderStyle(border)
+{
+ SetViewColor(B_TRANSPARENT_32_BIT);
+
+ BRect bounds(rect);
+ bounds.OffsetTo(0, 0);
+
+ for (int i = 0; i < (int)B_COLOR_TOTAL; i++)
+ fColorList[i] = kColor[i];
+
+ BRect titleRect(bounds);
+ titleRect.bottom = titleRect.top + kTitleHeight;
+#if !LOWER_SCROLLBAR
+ titleRect.right -= B_V_SCROLL_BAR_WIDTH + 1;
+#endif
+
+ BRect outlineRect(bounds);
+ outlineRect.top = titleRect.bottom + 1.0;
+ outlineRect.right -= B_V_SCROLL_BAR_WIDTH + 1;
+ if(showHorizontalScrollbar)
+ outlineRect.bottom -= B_H_SCROLL_BAR_HEIGHT + 1;
+
+ BRect vScrollBarRect(bounds);
+#if LOWER_SCROLLBAR
+ vScrollBarRect.top += kTitleHeight;
+#endif
+
+ vScrollBarRect.left = vScrollBarRect.right - B_V_SCROLL_BAR_WIDTH;
+ if(showHorizontalScrollbar)
+ vScrollBarRect.bottom -= B_H_SCROLL_BAR_HEIGHT;
+
+ BRect hScrollBarRect(bounds);
+ hScrollBarRect.top = hScrollBarRect.bottom - B_H_SCROLL_BAR_HEIGHT;
+ hScrollBarRect.right -= B_V_SCROLL_BAR_WIDTH;
+
+ // Adjust stuff so the border will fit.
+ if (fBorderStyle == B_PLAIN_BORDER) {
+ titleRect.InsetBy(1, 0);
+ titleRect.top++;
+ outlineRect.InsetBy(1, 0);
+ outlineRect.bottom--;
+
+ vScrollBarRect.OffsetBy(-1, 0);
+ vScrollBarRect.InsetBy(0, 1);
+ hScrollBarRect.OffsetBy(0, -1);
+ hScrollBarRect.InsetBy(1, 0);
+ } else if (fBorderStyle == B_FANCY_BORDER) {
+ titleRect.InsetBy(2, 0);
+ titleRect.top += 2;
+ outlineRect.InsetBy(2, 0);
+ outlineRect.bottom -= 2;
+
+ vScrollBarRect.OffsetBy(-2, 0);
+ vScrollBarRect.InsetBy(0, 2);
+ hScrollBarRect.OffsetBy(0, -2);
+ hScrollBarRect.InsetBy(2, 0);
+ }
+
+ fOutlineView = new OutlineView(outlineRect, &fColumns, &fSortColumns, this);
+ AddChild(fOutlineView);
+
+
+ // Adapt to correct resizing mode
+ uint32 fParentFlags = resizingMode;
+ // Always follow LEFT_RIGHT
+ uint32 fTitleFlags = B_FOLLOW_LEFT_RIGHT;
+
+ if ((fParentFlags & B_FOLLOW_TOP) && (fParentFlags & ~B_FOLLOW_BOTTOM)) {
+ fTitleFlags |= B_FOLLOW_TOP;
+ }
+ else if ((fParentFlags & B_FOLLOW_BOTTOM) && (fParentFlags & ~B_FOLLOW_TOP)) {
+ fTitleFlags |= B_FOLLOW_BOTTOM;
+ }
+
+ fTitleView = new TitleView(titleRect, fOutlineView, &fColumns, &fSortColumns, this, fTitleFlags);
+
+
+ AddChild(fTitleView);
+ fVerticalScrollBar = new BScrollBar(vScrollBarRect, "vertical_scroll_bar",
+ fOutlineView, 0.0, bounds.Height(), B_VERTICAL);
+ AddChild(fVerticalScrollBar);
+ fHorizontalScrollBar = new BScrollBar(hScrollBarRect, "horizontal_scroll_bar",
+ fTitleView, 0.0, bounds.Width(), B_HORIZONTAL);
+ AddChild(fHorizontalScrollBar);
+ if(!showHorizontalScrollbar)
+ fHorizontalScrollBar->Hide();
+ fOutlineView->FixScrollBar(true);
+}
+
+BColumnListView::~BColumnListView()
+{
+ while (true) {
+ BColumn *column = (BColumn*) fColumns.RemoveItem(0L);
+ if (column == 0)
+ break;
+
+ delete column;
+ }
+}
+
+bool BColumnListView::InitiateDrag(BPoint, bool)
+{
+ return false;
+}
+
+void BColumnListView::MessageDropped(BMessage*, BPoint)
+{
+}
+
+void BColumnListView::ExpandOrCollapse(BRow* Row, bool Open)
+{
+ fOutlineView->ExpandOrCollapse(Row, Open);
+}
+
+status_t BColumnListView::Invoke(BMessage *message)
+{
+ if (message == 0)
+ message = Message();
+
+ return BInvoker::Invoke(message);
+}
+
+void BColumnListView::ItemInvoked()
+{
+ Invoke();
+}
+
+void BColumnListView::SetInvocationMessage(BMessage *message)
+{
+ SetMessage(message);
+}
+
+BMessage* BColumnListView::InvocationMessage() const
+{
+ return Message();
+}
+
+uint32 BColumnListView::InvocationCommand() const
+{
+ return Command();
+}
+
+BRow* BColumnListView::FocusRow() const
+{
+ return fOutlineView->FocusRow();
+}
+
+void BColumnListView::SetFocusRow(int32 Index, bool Select)
+{
+ SetFocusRow(RowAt(Index), Select);
+}
+
+void BColumnListView::SetFocusRow(BRow* Row, bool Select)
+{
+ fOutlineView->SetFocusRow(Row, Select);
+}
+
+void BColumnListView::SetMouseTrackingEnabled(bool Enabled)
+{
+ fOutlineView->SetMouseTrackingEnabled(Enabled);
+}
+
+list_view_type BColumnListView::SelectionMode() const
+{
+ return fOutlineView->SelectionMode();
+}
+
+void BColumnListView::Deselect(BRow *row)
+{
+ fOutlineView->Deselect(row);
+}
+
+void BColumnListView::AddToSelection(BRow *row)
+{
+ fOutlineView->AddToSelection(row);
+}
+
+void BColumnListView::DeselectAll()
+{
+ fOutlineView->DeselectAll();
+}
+
+BRow* BColumnListView::CurrentSelection(BRow *lastSelected) const
+{
+ return fOutlineView->CurrentSelection(lastSelected);
+}
+
+void BColumnListView::SelectionChanged()
+{
+ if (fSelectionMessage)
+ Invoke(fSelectionMessage);
+}
+
+void BColumnListView::SetSelectionMessage(BMessage *message)
+{
+ if (fSelectionMessage == message)
+ return;
+
+ delete fSelectionMessage;
+ fSelectionMessage = message;
+}
+
+BMessage* BColumnListView::SelectionMessage()
+{
+ return fSelectionMessage;
+}
+
+uint32 BColumnListView::SelectionCommand() const
+{
+ if (fSelectionMessage)
+ return fSelectionMessage->what;
+
+ return 0;
+}
+
+void BColumnListView::SetSelectionMode(list_view_type mode)
+{
+ fOutlineView->SetSelectionMode(mode);
+}
+
+void BColumnListView::SetSortingEnabled(bool enabled)
+{
+ fSortingEnabled = enabled;
+ fSortColumns.MakeEmpty();
+ fTitleView->Invalidate(); // Erase sort indicators
+}
+
+bool BColumnListView::SortingEnabled() const
+{
+ return fSortingEnabled;
+}
+
+void BColumnListView::SetSortColumn(BColumn *column, bool add, bool ascending)
+{
+ if (!SortingEnabled())
+ return;
+
+ if (!add)
+ fSortColumns.MakeEmpty();
+
+ if (!fSortColumns.HasItem(column))
+ fSortColumns.AddItem(column);
+
+ column->fSortAscending = ascending;
+ fTitleView->Invalidate();
+ fOutlineView->StartSorting();
+}
+
+void BColumnListView::ClearSortColumns()
+{
+ fSortColumns.MakeEmpty();
+ fTitleView->Invalidate(); // Erase sort indicators
+}
+
+void BColumnListView::AddStatusView(BView *view)
+{
+ BRect bounds = Bounds();
+ float width = view->Bounds().Width();
+ if (width > bounds.Width() / 2)
+ width = bounds.Width() / 2;
+
+ fStatusView = view;
+
+ Window()->BeginViewTransaction();
+ fHorizontalScrollBar->ResizeBy(-(width + 1), 0);
+ fHorizontalScrollBar->MoveBy((width + 1), 0);
+ AddChild(view);
+
+ BRect viewRect(bounds);
+ viewRect.right = width;
+ viewRect.top = viewRect.bottom - B_H_SCROLL_BAR_HEIGHT;
+ if (fBorderStyle == B_PLAIN_BORDER)
+ viewRect.OffsetBy(1, -1);
+ else if (fBorderStyle == B_FANCY_BORDER)
+ viewRect.OffsetBy(2, -2);
+
+ view->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
+ view->ResizeTo(viewRect.Width(), viewRect.Height());
+ view->MoveTo(viewRect.left, viewRect.top);
+ Window()->EndViewTransaction();
+}
+
+BView* BColumnListView::RemoveStatusView()
+{
+ if (fStatusView) {
+ float width = fStatusView->Bounds().Width();
+ Window()->BeginViewTransaction();
+ fStatusView->RemoveSelf();
+ fHorizontalScrollBar->MoveBy(-width, 0);
+ fHorizontalScrollBar->ResizeBy(width, 0);
+ Window()->EndViewTransaction();
+ }
+
+ BView *view = fStatusView;
+ fStatusView = 0;
+ return view;
+}
+void BColumnListView::AddColumn(BColumn *column, int32 logicalFieldIndex)
+{
+ ASSERT(column != 0);
+
+ column->fList = this;
+ column->fFieldID = logicalFieldIndex;
+
+ // sanity check. If there is already a field with this ID, remove it.
+ for (int32 index = 0; index < fColumns.CountItems(); index++) {
+ BColumn *existingColumn = (BColumn*) fColumns.ItemAt(index);
+ if (existingColumn && existingColumn->fFieldID == logicalFieldIndex) {
+ RemoveColumn(existingColumn);
+ break;
+ }
+ }
+
+ if (column->Width() < column->MinWidth())
+ column->SetWidth(column->MinWidth());
+ else if (column->Width() > column->MaxWidth())
+ column->SetWidth(column->MaxWidth());
+
+ fColumns.AddItem((void*) column);
+ fTitleView->ColumnAdded(column);
+}
+
+void BColumnListView::MoveColumn(BColumn *column, int32 index)
+{
+ ASSERT(column != 0);
+ fTitleView->MoveColumn(column, index);
+}
+
+void BColumnListView::RemoveColumn(BColumn *column)
+{
+ if (fColumns.HasItem(column)) {
+ SetColumnVisible(column, false);
+ Window()->UpdateIfNeeded();
+ fColumns.RemoveItem(column);
+ }
+}
+
+int32 BColumnListView::CountColumns() const
+{
+ return fColumns.CountItems();
+}
+
+BColumn* BColumnListView::ColumnAt(int32 field) const
+{
+ return (BColumn*) fColumns.ItemAt(field);
+}
+
+void BColumnListView::SetColumnVisible(BColumn *column, bool visible)
+{
+ fTitleView->SetColumnVisible(column, visible);
+}
+
+void BColumnListView::SetColumnVisible(int32 index, bool isVisible)
+{
+ BColumn *column = ColumnAt(index);
+ if (column)
+ column->SetVisible(isVisible);
+}
+
+bool BColumnListView::IsColumnVisible(int32 index) const
+{
+ BColumn *column = ColumnAt(index);
+ if (column)
+ return column->IsVisible();
+
+ return false;
+}
+
+void BColumnListView::SetColumnFlags(column_flags flags)
+{
+ fTitleView->SetColumnFlags(flags);
+}
+
+const BRow* BColumnListView::RowAt(int32 Index, BRow* ParentRow) const
+{
+ if (ParentRow == 0)
+ return fOutlineView->RowList()->ItemAt(Index);
+
+ return ParentRow->fChildList ? ParentRow->fChildList->ItemAt(Index) : NULL;
+}
+
+BRow* BColumnListView::RowAt(int32 Index, BRow* ParentRow)
+{
+ if (ParentRow == 0)
+ return fOutlineView->RowList()->ItemAt(Index);
+
+ return ParentRow->fChildList ? ParentRow->fChildList->ItemAt(Index) : 0;
+}
+
+const BRow* BColumnListView::RowAt(BPoint point) const
+{
+ float top;
+ int32 indent;
+ return fOutlineView->FindRow(point.y, &indent, &top);
+}
+
+BRow* BColumnListView::RowAt(BPoint point)
+{
+ float top;
+ int32 indent;
+ return fOutlineView->FindRow(point.y, &indent, &top);
+}
+
+bool BColumnListView::GetRowRect(const BRow *row, BRect *outRect) const
+{
+ return fOutlineView->FindRect(row, outRect);
+}
+
+bool BColumnListView::FindParent(BRow *row, BRow **out_parent, bool *out_isVisible) const
+{
+ return fOutlineView->FindParent(row, out_parent, out_isVisible);
+}
+
+int32 BColumnListView::IndexOf(BRow *row)
+{
+ return fOutlineView->IndexOf(row);
+}
+
+int32 BColumnListView::CountRows(BRow* ParentRow) const
+{
+ if (ParentRow == 0)
+ return fOutlineView->RowList()->CountItems();
+ if (ParentRow->fChildList)
+ return ParentRow->fChildList->CountItems();
+ else
+ return 0;
+}
+
+void BColumnListView::AddRow(BRow *row, BRow* ParentRow)
+{
+ AddRow(row, -1, ParentRow);
+}
+
+void BColumnListView::AddRow(BRow *row, int32 index, BRow* ParentRow)
+{
+ row->fChildList = 0;
+ row->fList = this;
+ row->ValidateFields();
+ fOutlineView->AddRow(row, index, ParentRow);
+}
+
+void BColumnListView::RemoveRow(BRow *row)
+{
+ fOutlineView->RemoveRow(row);
+ row->fList = NULL;
+}
+
+void BColumnListView::UpdateRow(BRow *row)
+{
+ fOutlineView->UpdateRow(row);
+}
+
+void BColumnListView::ScrollTo(const BRow* Row)
+{
+ fOutlineView->ScrollTo(Row);
+}
+
+void BColumnListView::Clear()
+{
+ fOutlineView->Clear();
+}
+
+void BColumnListView::SetFont(const BFont *font, uint32 mask)
+{
+ // This method is deprecated.
+ fOutlineView->SetFont(font, mask);
+ fTitleView->SetFont(font, mask);
+}
+
+void BColumnListView::SetFont(ColumnListViewFont font_num, const BFont* font, uint32 mask)
+{
+ switch (font_num) {
+ case B_FONT_ROW:
+ fOutlineView->SetFont(font, mask);
+ break;
+
+ case B_FONT_HEADER:
+ fTitleView->SetFont(font, mask);
+ break;
+
+ default:
+ ASSERT(false);
+ break;
+ };
+}
+
+void BColumnListView::GetFont(ColumnListViewFont font_num, BFont* font) const
+{
+ switch (font_num) {
+ case B_FONT_ROW:
+ fOutlineView->GetFont(font);
+ break;
+
+ case B_FONT_HEADER:
+ fTitleView->GetFont(font);
+ break;
+
+ default:
+ ASSERT(false);
+ break;
+ };
+}
+
+void BColumnListView::SetColor(ColumnListViewColor color_num, const rgb_color color)
+{
+ if ((int)color_num < 0)
+ {
+ ASSERT(false);
+ color_num = (ColumnListViewColor) 0;
+ }
+
+ if ((int)color_num >= (int)B_COLOR_TOTAL)
+ {
+ ASSERT(false);
+ color_num = (ColumnListViewColor) (B_COLOR_TOTAL - 1);
+ }
+
+ fColorList[color_num] = color;
+}
+
+rgb_color BColumnListView::Color(ColumnListViewColor color_num) const
+{
+ if ((int)color_num < 0)
+ {
+ ASSERT(false);
+ color_num = (ColumnListViewColor) 0;
+ }
+
+ if ((int)color_num >= (int)B_COLOR_TOTAL)
+ {
+ ASSERT(false);
+ color_num = (ColumnListViewColor) (B_COLOR_TOTAL - 1);
+ }
+
+ return fColorList[color_num];
+}
+
+void BColumnListView::SetHighColor(rgb_color color)
+{
+ BView::SetHighColor(color);
+// fOutlineView->Invalidate(); // Redraw things with the new color
+ // Note that this will currently cause
+ // an infinite loop, refreshing over and over.
+ // A better solution is needed.
+}
+
+void BColumnListView::SetSelectionColor(rgb_color color)
+{
+ fColorList[B_COLOR_SELECTION] = color;
+}
+
+void BColumnListView::SetBackgroundColor(rgb_color color)
+{
+ fColorList[B_COLOR_BACKGROUND] = color;
+ fOutlineView->Invalidate(); // Repaint with new color
+}
+
+void BColumnListView::SetEditColor(rgb_color color)
+{
+ fColorList[B_COLOR_EDIT_BACKGROUND] = color;
+}
+
+const rgb_color BColumnListView::SelectionColor() const
+{
+ return fColorList[B_COLOR_SELECTION];
+}
+
+const rgb_color BColumnListView::BackgroundColor() const
+{
+ return fColorList[B_COLOR_BACKGROUND];
+}
+
+const rgb_color BColumnListView::EditColor() const
+{
+ return fColorList[B_COLOR_EDIT_BACKGROUND];
+}
+
+BPoint BColumnListView::SuggestTextPosition(const BRow* row, const BColumn* inColumn) const
+{
+ BRect rect;
+ GetRowRect(row, &rect);
+ if (inColumn) {
+ float leftEdge = MAX(kLeftMargin, LatchWidth());
+ for (int index = 0; index < fColumns.CountItems(); index++) {
+ BColumn *column = (BColumn*) fColumns.ItemAt(index);
+ if (!column->IsVisible())
+ continue;
+
+ if (column == inColumn) {
+ rect.left = leftEdge;
+ rect.right = rect.left + column->Width();
+ break;
+ }
+
+ leftEdge += column->Width() + 1;
+ }
+ }
+
+ font_height fh;
+ fOutlineView->GetFontHeight(&fh);
+ float baseline = floor(rect.top + fh.ascent
+ + (rect.Height()+1-(fh.ascent+fh.descent))/2);
+ return BPoint(rect.left + 8, baseline);
+}
+
+void BColumnListView::SetLatchWidth(float width)
+{
+ fLatchWidth = width;
+ Invalidate();
+}
+
+float BColumnListView::LatchWidth() const
+{
+ return fLatchWidth;
+}
+
+void BColumnListView::DrawLatch(BView *view, BRect rect, LatchType position, BRow *)
+{
+ const int32 rectInset = 4;
+
+ view->SetHighColor(0, 0, 0);
+
+ // Make Square
+ int32 sideLen = rect.IntegerWidth();
+ if( sideLen > rect.IntegerHeight() )
+ {
+ sideLen = rect.IntegerHeight();
+ }
+
+ // Make Center
+ int32 halfWidth = rect.IntegerWidth() / 2;
+ int32 halfHeight = rect.IntegerHeight() / 2;
+ int32 halfSide = sideLen / 2;
+
+ float left = rect.left + halfWidth - halfSide;
+ float top = rect.top + halfHeight - halfSide;
+
+ BRect itemRect(left, top, left + sideLen, top + sideLen);
+
+ // Why it is a pixel high? I don't know.
+ itemRect.OffsetBy(0, -1);
+
+ itemRect.InsetBy(rectInset, rectInset);
+
+ // Make it an odd number of pixels wide, the latch looks better this way
+ if (1 == (itemRect.IntegerWidth() % 2))
+ {
+ itemRect.right += 1;
+ itemRect.bottom += 1;
+ }
+
+ switch (position) {
+ case B_OPEN_LATCH:
+ view->StrokeRect(itemRect);
+ view->StrokeLine(BPoint(itemRect.left + 2, (itemRect.top + itemRect.bottom) / 2),
+ BPoint(itemRect.right - 2, (itemRect.top + itemRect.bottom) / 2));
+ break;
+
+ case B_PRESSED_LATCH:
+ view->StrokeRect(itemRect);
+ view->StrokeLine(BPoint(itemRect.left + 2, (itemRect.top + itemRect.bottom) / 2),
+ BPoint(itemRect.right - 2, (itemRect.top + itemRect.bottom) / 2));
+ view->StrokeLine(BPoint((itemRect.left + itemRect.right) / 2, itemRect.top + 2),
+ BPoint((itemRect.left + itemRect.right) / 2, itemRect.bottom - 2));
+ view->InvertRect(itemRect);
+ break;
+
+ case B_CLOSED_LATCH:
+ view->StrokeRect(itemRect);
+ view->StrokeLine(BPoint(itemRect.left + 2, (itemRect.top + itemRect.bottom) / 2),
+ BPoint(itemRect.right - 2, (itemRect.top + itemRect.bottom) / 2));
+ view->StrokeLine(BPoint((itemRect.left + itemRect.right) / 2, itemRect.top + 2),
+ BPoint((itemRect.left + itemRect.right) / 2, itemRect.bottom - 2));
+ break;
+
+ case B_NO_LATCH:
+ // No drawing
+ break;
+ }
+}
+
+void BColumnListView::MakeFocus(bool isFocus)
+{
+ Invalidate(); // Redraw focus marks around view
+ BView::MakeFocus(isFocus);
+}
+
+void BColumnListView::MessageReceived(BMessage *message)
+{
+ // Propagate mouse wheel messages down to child, so that it can
+ // scroll. Note we have done so, so we don't go into infinite
+ // recursion if this comes back up here.
+ if (message->what == B_MOUSE_WHEEL_CHANGED) {
+ bool handled;
+ if (message->FindBool("be:clvhandled", &handled) != B_OK) {
+ message->AddBool("be:clvhandled", true);
+ fOutlineView->MessageReceived(message);
+ return;
+ }
+ }
+ BView::MessageReceived(message);
+}
+
+void BColumnListView::KeyDown(const char *bytes, int32 numBytes)
+{
+ char c = bytes[0];
+ switch (c) {
+ case B_RIGHT_ARROW:
+ case B_LEFT_ARROW: {
+ float minVal, maxVal;
+ fHorizontalScrollBar->GetRange(&minVal, &maxVal);
+ float smallStep, largeStep;
+ fHorizontalScrollBar->GetSteps(&smallStep, &largeStep);
+ float oldVal = fHorizontalScrollBar->Value();
+ float newVal = oldVal;
+
+ if (c == B_LEFT_ARROW)
+ newVal -= smallStep;
+ else if (c == B_RIGHT_ARROW)
+ newVal += smallStep;
+
+ if (newVal < minVal)
+ newVal = minVal;
+ else if (newVal > maxVal)
+ newVal = maxVal;
+
+ fHorizontalScrollBar->SetValue(newVal);
+ break;
+ }
+
+ case B_DOWN_ARROW:
+ fOutlineView->ChangeFocusRow(false, (modifiers() & B_CONTROL_KEY) == 0,
+ (modifiers() & B_SHIFT_KEY) != 0);
+ break;
+
+ case B_UP_ARROW:
+ fOutlineView->ChangeFocusRow(true, (modifiers() & B_CONTROL_KEY) == 0,
+ (modifiers() & B_SHIFT_KEY) != 0);
+ break;
+
+ case B_PAGE_UP:
+ case B_PAGE_DOWN: {
+ float minValue, maxValue;
+ fVerticalScrollBar->GetRange(&minValue, &maxValue);
+ float smallStep, largeStep;
+ fVerticalScrollBar->GetSteps(&smallStep, &largeStep);
+ float currentValue = fVerticalScrollBar->Value();
+ float newValue = currentValue;
+
+ if (c == B_PAGE_UP)
+ newValue -= largeStep;
+ else
+ newValue += largeStep;
+
+ if (newValue > maxValue)
+ newValue = maxValue;
+ else if (newValue < minValue)
+ newValue = minValue;
+
+ fVerticalScrollBar->SetValue(newValue);
+
+ // Option + pgup or pgdn scrolls and changes the selection.
+ if (modifiers() & B_OPTION_KEY)
+ fOutlineView->MoveFocusToVisibleRect();
+
+ break;
+ }
+
+ case B_ENTER:
+ Invoke();
+ break;
+
+ case B_SPACE:
+ fOutlineView->ToggleFocusRowSelection((modifiers() & B_SHIFT_KEY) != 0);
+ break;
+
+ case '+':
+ fOutlineView->ToggleFocusRowOpen();
+ break;
+
+ default:
+ BView::KeyDown(bytes, numBytes);
+ }
+}
+
+void BColumnListView::AttachedToWindow()
+{
+ if (!Messenger().IsValid())
+ SetTarget(Window());
+
+ if (SortingEnabled()) fOutlineView->StartSorting();
+}
+
+void BColumnListView::WindowActivated(bool active)
+{
+ fOutlineView->Invalidate();
+ // Focus and selection appearance changes with focus
+
+ Invalidate(); // Redraw focus marks around view
+ BView::WindowActivated(active);
+}
+
+void BColumnListView::Draw(BRect)
+{
+ BRect rect = Bounds();
+ PushState();
+
+ BRect cornerRect(rect.right - B_V_SCROLL_BAR_WIDTH, rect.bottom - B_H_SCROLL_BAR_HEIGHT,
+ rect.right, rect.bottom);
+ if (fBorderStyle == B_PLAIN_BORDER) {
+ BView::SetHighColor(0, 0, 0);
+ StrokeRect(rect);
+ cornerRect.OffsetBy(-1, -1);
+ } else if (fBorderStyle == B_FANCY_BORDER) {
+ bool isFocus = IsFocus() && Window()->IsActive();
+
+ if (isFocus)
+ BView::SetHighColor(0, 0, 190); // Need to find focus color programatically
+ else
+ BView::SetHighColor(255, 255, 255);
+
+ StrokeRect(rect);
+ if (!isFocus)
+ BView::SetHighColor(184, 184, 184);
+ else
+ BView::SetHighColor(152, 152, 152);
+
+ rect.InsetBy(1,1);
+ StrokeRect(rect);
+ cornerRect.OffsetBy(-2, -2);
+ }
+
+ BView::SetHighColor(215, 215, 215); // fills lower right rect between scroll bars
+ FillRect(cornerRect);
+ PopState();
+}
+
+void BColumnListView::SaveState(BMessage *msg)
+{
+ msg->MakeEmpty();
+
+ // Damn compiler issuing l43m incorrect warnings.
+ int i;
+ for (i = 0; ;i++)
+ {
+ BColumn *col = (BColumn*) fColumns.ItemAt(i);
+ if(!col)
+ break;
+ msg->AddInt32("ID",col->fFieldID);
+ msg->AddFloat("width",col->fWidth);
+ msg->AddBool("visible",col->fVisible);
+ }
+
+ msg->AddBool("sortingenabled",fSortingEnabled);
+
+ if(fSortingEnabled)
+ {
+ for (i = 0; ;i++)
+ {
+ BColumn *col = (BColumn*) fSortColumns.ItemAt(i);
+ if(!col)
+ break;
+ msg->AddInt32("sortID",col->fFieldID);
+ msg->AddBool("sortascending",col->fSortAscending);
+ }
+ }
+}
+
+void BColumnListView::LoadState(BMessage *msg)
+{
+ for(int i=0;;i++)
+ {
+ int32 ID;
+ if(B_OK!=msg->FindInt32("ID",i,&ID))
+ break;
+ for(int j=0;;j++)
+ {
+ BColumn *col = (BColumn*) fColumns.ItemAt(j);
+ if(!col)
+ break;
+ if(col->fFieldID==ID)
+ {
+ // move this column to position 'i' and set its attributes
+ MoveColumn(col,i);
+ float f;
+ if(B_OK==msg->FindFloat("width",i,&f))
+ col->SetWidth(f);
+ bool b;
+ if(B_OK==msg->FindBool("visible",i,&b))
+ col->SetVisible(b);
+ }
+ }
+ }
+ bool b;
+ if(B_OK==msg->FindBool("sortingenabled",&b))
+ {
+ SetSortingEnabled(b);
+ // Damn compiler issuing l43m incorrect warnings.
+ for(int k=0;;k++)
+ {
+ int32 ID;
+ if(B_OK!=msg->FindInt32("sortID", k, &ID))
+ break;
+ for(int j=0;;j++)
+ {
+ BColumn *col = (BColumn*) fColumns.ItemAt(j);
+ if(!col)
+ break;
+ if(col->fFieldID==ID)
+ {
+ // add this column to the sort list
+ bool val;
+ if(B_OK==msg->FindBool("sortascending", k, &val))
+ SetSortColumn(col, true, val);
+ }
+ }
+ }
+ }
+}
+
+void BColumnListView::SetEditMode(bool state)
+{
+ fOutlineView->SetEditMode(state);
+ fTitleView->SetEditMode(state);
+}
+
+void BColumnListView::Refresh()
+{
+ if(LockLooper())
+ {
+ Invalidate();
+ fOutlineView->FixScrollBar (true);
+ fOutlineView->Invalidate();
+ Window()->UpdateIfNeeded();
+ UnlockLooper();
+ }
+}
+
+// #pragma mark -
+
+
+TitleView::TitleView(BRect rect, OutlineView *horizontalSlave, BList *visibleColumns,
+ BList *sortColumns, BColumnListView *listView, uint32 resizingMode)
+ : BView(rect, "title_view", resizingMode, B_WILL_DRAW | B_FRAME_EVENTS),
+ fOutlineView(horizontalSlave),
+ fColumns(visibleColumns),
+ fSortColumns(sortColumns),
+ fColumnsWidth(0),
+ fVisibleRect(rect.OffsetToCopy(0, 0)),
+ fCurrentState(INACTIVE),
+ fColumnPop(NULL),
+ fMasterView(listView),
+ fEditMode(false),
+ fColumnFlags(B_ALLOW_COLUMN_MOVE|B_ALLOW_COLUMN_RESIZE|B_ALLOW_COLUMN_POPUP|B_ALLOW_COLUMN_REMOVE)
+{
+ SetViewColor(B_TRANSPARENT_32_BIT);
+
+#if DOUBLE_BUFFERED_COLUMN_RESIZE
+ // xxx this needs to be smart about the size of the backbuffer.
+ BRect doubleBufferRect(0, 0, 600, 35);
+ fDrawBuffer = new BBitmap(doubleBufferRect, B_RGB32, true);
+ fDrawBufferView = new BView(doubleBufferRect, "double_buffer_view",
+ B_FOLLOW_ALL_SIDES, 0);
+ fDrawBuffer->Lock();
+ fDrawBuffer->AddChild(fDrawBufferView);
+ fDrawBuffer->Unlock();
+#endif
+
+ fUpSortArrow = new BBitmap(BRect(0, 0, 7, 7), B_COLOR_8_BIT);
+ fDownSortArrow = new BBitmap(BRect(0, 0, 7, 7), B_COLOR_8_BIT);
+
+ fUpSortArrow->SetBits((const void*) kUpSortArrow8x8, 64, 0, B_COLOR_8_BIT);
+ fDownSortArrow->SetBits((const void*) kDownSortArrow8x8, 64, 0, B_COLOR_8_BIT);
+
+#if _INCLUDES_CLASS_CURSOR
+ fResizeCursor = new BCursor(kResizeCursorData);
+ fMinResizeCursor = new BCursor(kMinResizeCursorData);
+ fMaxResizeCursor = new BCursor(kMaxResizeCursorData);
+ fColumnMoveCursor = new BCursor(kColumnMoveCursorData);
+#endif
+ FixScrollBar(true);
+}
+
+TitleView::~TitleView()
+{
+ delete fColumnPop;
+ fColumnPop = NULL;
+
+ fDrawBuffer->Lock();
+ fDrawBufferView->RemoveSelf();
+ fDrawBuffer->Unlock();
+ delete fDrawBufferView;
+ delete fDrawBuffer;
+ delete fUpSortArrow;
+ delete fDownSortArrow;
+
+#if _INCLUDES_CLASS_CURSOR
+ delete fResizeCursor;
+ delete fMaxResizeCursor;
+ delete fMinResizeCursor;
+ delete fColumnMoveCursor;
+#endif
+}
+
+void TitleView::ColumnAdded(BColumn *column)
+{
+ fColumnsWidth += column->Width() + 1;
+ FixScrollBar(false);
+ Invalidate();
+}
+// Could use a CopyBits here.
+void TitleView::SetColumnVisible(BColumn *column, bool visible)
+{
+ if (column->fVisible == visible)
+ return;
+
+ // If setting it visible, do this first so we can find its position
+ // to invalidate. If hiding it, do it last.
+ if (visible)
+ column->fVisible = visible;
+
+ BRect titleInvalid;
+ GetTitleRect(column, &titleInvalid);
+
+ // Now really set the visibility
+ column->fVisible = visible;
+
+ if (visible)
+ fColumnsWidth += column->Width();
+ else
+ fColumnsWidth -= column->Width();
+
+ BRect outlineInvalid(fOutlineView->VisibleRect());
+ outlineInvalid.left = titleInvalid.left;
+ titleInvalid.right = outlineInvalid.right;
+
+ Invalidate(titleInvalid);
+ fOutlineView->Invalidate(outlineInvalid);
+}
+
+void TitleView::GetTitleRect(BColumn *findColumn, BRect *out_rect)
+{
+ float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth());
+ int32 numColumns = fColumns->CountItems();
+ for (int index = 0; index < numColumns; index++) {
+ BColumn *column = (BColumn*) fColumns->ItemAt(index);
+ if (!column->IsVisible())
+ continue;
+
+ if (column == findColumn) {
+ out_rect->Set(leftEdge, 0, leftEdge + column->Width(), fVisibleRect.bottom);
+ return;
+ }
+
+ leftEdge += column->Width() + 1;
+ }
+
+ TRESPASS();
+}
+
+int32 TitleView::FindColumn(BPoint position, float *out_leftEdge)
+{
+ float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth());
+ int32 numColumns = fColumns->CountItems();
+ for (int index = 0; index < numColumns; index++) {
+ BColumn *column = (BColumn*) fColumns->ItemAt(index);
+ if (!column->IsVisible())
+ continue;
+
+ if (leftEdge > position.x)
+ break;
+
+ if (position.x >= leftEdge && position.x <= leftEdge + column->Width()) {
+ *out_leftEdge = leftEdge;
+ return index;
+ }
+
+ leftEdge += column->Width() + 1;
+ }
+
+ return 0;
+}
+
+void TitleView::FixScrollBar(bool scrollToFit)
+{
+ BScrollBar *hScrollBar = ScrollBar(B_HORIZONTAL);
+ if (hScrollBar) {
+ float virtualWidth = fColumnsWidth + MAX(kLeftMargin, fMasterView->LatchWidth()) +
+ kRightMargin * 2;
+
+ if (virtualWidth > fVisibleRect.Width()) {
+ hScrollBar->SetProportion(fVisibleRect.Width() / virtualWidth);
+
+ // Perform the little trick if the user is scrolled over too far.
+ // See OutlineView::FixScrollBar for a more in depth explanation
+ float maxScrollBarValue = virtualWidth - fVisibleRect.Width();
+ if (scrollToFit || hScrollBar->Value() <= maxScrollBarValue) {
+ hScrollBar->SetRange(0.0, maxScrollBarValue);
+ hScrollBar->SetSteps(50, fVisibleRect.Width());
+ }
+ } else if (hScrollBar->Value() == 0.0)
+ hScrollBar->SetRange(0.0, 0.0); // disable scroll bar.
+ }
+}
+
+void TitleView::DragSelectedColumn(BPoint position)
+{
+ float invalidLeft = fSelectedColumnRect.left;
+ float invalidRight = fSelectedColumnRect.right;
+
+ float leftEdge;
+ int32 columnIndex = FindColumn(position, &leftEdge);
+ fSelectedColumnRect.OffsetTo(leftEdge, 0);
+
+ MoveColumn(fSelectedColumn, columnIndex);
+
+ fSelectedColumn->fVisible = true;
+ ComputeDragBoundries(fSelectedColumn, position);
+
+ // Redraw the new column position
+ GetTitleRect(fSelectedColumn, &fSelectedColumnRect);
+ invalidLeft = MIN(fSelectedColumnRect.left, invalidLeft);
+ invalidRight = MAX(fSelectedColumnRect.right, invalidRight);
+
+ Invalidate(BRect(invalidLeft, 0, invalidRight, fVisibleRect.bottom));
+ fOutlineView->Invalidate(BRect(invalidLeft, 0, invalidRight,
+ fOutlineView->VisibleRect().bottom));
+
+ DrawTitle(this, fSelectedColumnRect, fSelectedColumn, true);
+}
+
+void TitleView::MoveColumn(BColumn *column, int32 index)
+{
+ fColumns->RemoveItem((void*) column);
+
+ if (-1 == index)
+ {
+ // Re-add the column at the end of the list.
+ fColumns->AddItem((void*) column);
+ }
+ else
+ {
+ fColumns->AddItem((void*) column, index);
+ }
+}
+
+void TitleView::SetColumnFlags(column_flags flags)
+{
+ fColumnFlags = flags;
+}
+
+
+void TitleView::ResizeSelectedColumn(BPoint position)
+{
+ float minWidth = fSelectedColumn->MinWidth();
+ float maxWidth = fSelectedColumn->MaxWidth();
+
+ float originalEdge = fSelectedColumnRect.left + fSelectedColumn->Width();
+ if (position.x > fSelectedColumnRect.left + maxWidth)
+ fSelectedColumn->SetWidth(maxWidth);
+ else if (position.x < fSelectedColumnRect.left + minWidth)
+ fSelectedColumn->SetWidth(minWidth);
+ else
+ fSelectedColumn->SetWidth(position.x - fSelectedColumnRect.left - 1);
+
+ float dX = fSelectedColumnRect.left + fSelectedColumn->Width() - originalEdge;
+ if (dX != 0) {
+ BRect originalRect(originalEdge, 0, 1000000.0, fVisibleRect.Height());
+ BRect movedRect(originalRect);
+ movedRect.OffsetBy(dX, 0);
+
+ // Update the size of the title column
+ BRect sourceRect(0, 0, fSelectedColumn->Width(), fVisibleRect.Height());
+ BRect destRect(sourceRect);
+ destRect.OffsetBy(fSelectedColumnRect.left, 0);
+
+#if DOUBLE_BUFFERED_COLUMN_RESIZE
+ fDrawBuffer->Lock();
+ fDrawBufferView->SetHighColor(fMasterView->Color(B_COLOR_HEADER_BACKGROUND));
+ fDrawBufferView->FillRect(sourceRect);
+ DrawTitle(fDrawBufferView, sourceRect, fSelectedColumn, false);
+ fDrawBufferView->Sync();
+ fDrawBuffer->Unlock();
+
+ CopyBits(originalRect, movedRect);
+ DrawBitmap(fDrawBuffer, sourceRect, destRect);
+#else
+ CopyBits(originalRect, movedRect);
+ SetHighColor(fMasterView->Color(B_COLOR_HEADER_BACKGROUND));
+ FillRect(destRect);
+ DrawTitle(this, destRect, fSelectedColumn, false);
+#endif
+
+ // Update the body view
+ BRect slaveSize = fOutlineView->VisibleRect();
+ BRect slaveSource(originalRect);
+ slaveSource.bottom = slaveSize.bottom;
+ BRect slaveDest(movedRect);
+ slaveDest.bottom = slaveSize.bottom;
+ fOutlineView->CopyBits(slaveSource, slaveDest);
+ fOutlineView->RedrawColumn(fSelectedColumn, fSelectedColumnRect.left,
+ fResizingFirstColumn);
+
+ fColumnsWidth += dX;
+
+ // Update the cursor
+#if _INCLUDES_CLASS_CURSOR
+ if (fSelectedColumn->Width() == minWidth)
+ SetViewCursor(fMinResizeCursor, false);
+ else if (fSelectedColumn->Width() == maxWidth)
+ SetViewCursor(fMaxResizeCursor, false);
+ else
+ SetViewCursor(fResizeCursor, false);
+#endif
+ }
+}
+
+void TitleView::ComputeDragBoundries(BColumn *findColumn, BPoint )
+{
+ float previousColumnLeftEdge = -1000000.0;
+ float nextColumnRightEdge = 1000000.0;
+
+ bool foundColumn = false;
+ float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth());
+ int32 numColumns = fColumns->CountItems();
+ for (int index = 0; index < numColumns; index++) {
+ BColumn *column = (BColumn*) fColumns->ItemAt(index);
+ if (!column->IsVisible())
+ continue;
+
+ if (column == findColumn) {
+ foundColumn = true;
+ continue;
+ }
+
+ if (foundColumn) {
+ nextColumnRightEdge = leftEdge + column->Width();
+ break;
+ } else
+ previousColumnLeftEdge = leftEdge;
+
+ leftEdge += column->Width() + 1;
+ }
+
+ float rightEdge = leftEdge + findColumn->Width();
+
+ fLeftDragBoundry = MIN(previousColumnLeftEdge + findColumn->Width(), leftEdge);
+ fRightDragBoundry = MAX(nextColumnRightEdge, rightEdge);
+}
+
+void TitleView::DrawTitle(BView *view, BRect rect, BColumn *column, bool depressed)
+{
+ BRect drawRect;
+#ifndef HAIKU
+ rgb_color borderColor = mix_color(fMasterView->Color(B_COLOR_HEADER_BACKGROUND), BExperimental::make_color(0, 0, 0), 128);
+#else
+ rgb_color borderColor = mix_color(fMasterView->Color(B_COLOR_HEADER_BACKGROUND), make_color(0, 0, 0), 128);
+#endif
+ rgb_color backgroundColor;
+
+ rgb_color bevelHigh;
+ rgb_color bevelLow;
+ // Want exterior borders to overlap.
+ rect.right += 1;
+ drawRect = rect;
+ drawRect.InsetBy(2, 2);
+ if (...
[truncated message content] |