No GPL code allowed.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@661 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Phipps 2002-08-09 00:39:45 +00:00
parent 09c9c0c147
commit 10cde11f08
23 changed files with 0 additions and 6029 deletions

View File

@ -1,213 +0,0 @@
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
//Conventions:
// Global constants (declared with const) and #defines - all uppercase letters with words separated
// by underscores.
// (E.G., #define MY_DEFINE 5).
// (E.G., const int MY_CONSTANT = 5;).
// New data types (classes, structs, typedefs, etc.) - begin with an uppercase letter followed by
// lowercase words separated by uppercase letters. Enumerated constants contain a prefix
// associating them with a particular enumerated set.
// (E.G., typedef int MyTypedef;).
// (E.G., enum MyEnumConst {MEC_ONE, MEC_TWO};)
// Global variables - begin with "g_" followed by lowercase words separated by underscores.
// (E.G., int g_my_global;).
// Argument and local variables - begin with a lowercase letter followed by
// lowercase words separated by underscores.
// (E.G., int my_local;).
// Member variables - begin with "m_" followed by lowercase words separated by underscores.
// (E.G., int m_my_member;).
// Functions (member or global) - begin with an uppercase letter followed by lowercase words
// separated by uppercase letters.
// (E.G., void MyFunction(void);).
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include "BetterScrollView.h"
#include "Colors.h"
//******************************************************************************************************
//**** BetterScrollView CLASS
//******************************************************************************************************
#include <stdio.h>
BetterScrollView::BetterScrollView(const char *name, BView *target, uint32 resizeMask, uint32 flags,
bool horizontal, bool vertical, bool scroll_view_corner, border_style border)
: BScrollView(name, target, resizeMask, flags, horizontal, vertical, border)
{
m_target = target;
m_data_rect.Set(-1,-1,-1,-1);
m_h_scrollbar = ScrollBar(B_HORIZONTAL);
m_v_scrollbar = ScrollBar(B_VERTICAL);
if(scroll_view_corner && horizontal && vertical)
{
m_scroll_view_corner = new ScrollViewCorner(m_v_scrollbar->Frame().left,
m_h_scrollbar->Frame().top);
AddChild(m_scroll_view_corner);
}
else
m_scroll_view_corner = NULL;
}
BetterScrollView::~BetterScrollView()
{ }
void BetterScrollView::SetDataRect(BRect data_rect, bool scrolling_allowed)
{
m_data_rect = data_rect;
UpdateScrollBars(scrolling_allowed);
}
void BetterScrollView::FrameResized(float new_width, float new_height)
{
BScrollView::FrameResized(new_width,new_height);
UpdateScrollBars(true);
}
void BetterScrollView::AttachedToWindow()
{
BScrollView::AttachedToWindow();
UpdateScrollBars(false);
}
void BetterScrollView::UpdateScrollBars(bool scrolling_allowed)
{
//Figure out the bounds and scroll if necessary
BRect view_bounds = m_target->Bounds();
float page_width, page_height, view_width, view_height;
view_width = view_bounds.right-view_bounds.left;
view_height = view_bounds.bottom-view_bounds.top;
float min,max;
if(scrolling_allowed)
{
//Figure out the width of the page rectangle
page_width = m_data_rect.right-m_data_rect.left;
page_height = m_data_rect.bottom-m_data_rect.top;
if(view_width > page_width)
page_width = view_width;
if(view_height > page_height)
page_height = view_height;
//Adjust positions
float delta_x = 0.0;
if(m_h_scrollbar)
{
if(view_bounds.left < m_data_rect.left)
delta_x = m_data_rect.left - view_bounds.left;
else if(view_bounds.right > m_data_rect.left+page_width)
delta_x = m_data_rect.left+page_width - view_bounds.right;
}
float delta_y = 0.0;
if(m_v_scrollbar)
{
if(view_bounds.top < m_data_rect.top)
delta_y = m_data_rect.top - view_bounds.top;
else if(view_bounds.bottom > m_data_rect.top+page_height)
delta_y = m_data_rect.top+page_height - view_bounds.bottom;
}
if(delta_x != 0.0 || delta_y != 0.0)
{
m_target->ScrollTo(BPoint(view_bounds.left+delta_x,view_bounds.top+delta_y));
view_bounds = Bounds();
}
}
else
{
min = m_data_rect.left;
if(view_bounds.left < min)
min = view_bounds.left;
max = m_data_rect.right;
if(view_bounds.right > max)
max = view_bounds.right;
page_width = max-min;
min = m_data_rect.top;
if(view_bounds.top < min)
min = view_bounds.top;
max = m_data_rect.bottom;
if(view_bounds.bottom > max)
max = view_bounds.bottom;
page_height = max-min;
}
//Figure out the ratio of the bounds rectangle width or height to the page rectangle width or height
float width_prop = view_width/page_width;
float height_prop = view_height/page_height;
//Set the scroll bar ranges and proportions. If the whole document is visible, inactivate the
//slider
bool active_scroller = false;
if(m_h_scrollbar)
{
if(width_prop >= 1.0)
m_h_scrollbar->SetRange(0.0,0.0);
else
{
min = m_data_rect.left;
max = m_data_rect.left + page_width - view_width;
if(view_bounds.left < min)
min = view_bounds.left;
if(view_bounds.left > max)
max = view_bounds.left;
m_h_scrollbar->SetRange(min,max);
m_h_scrollbar->SetSteps(ceil(view_width/20), view_width);
active_scroller = true;
}
m_h_scrollbar->SetProportion(width_prop);
}
if(m_v_scrollbar)
{
if(height_prop >= 1.0)
m_v_scrollbar->SetRange(0.0,0.0);
else
{
min = m_data_rect.top;
max = m_data_rect.top + page_height - view_height;
if(view_bounds.top < min)
min = view_bounds.top;
if(view_bounds.top > max)
max = view_bounds.top;
m_v_scrollbar->SetRange(min,max);
m_v_scrollbar->SetSteps(ceil(view_height/20), view_height);
active_scroller = true;
}
m_v_scrollbar->SetProportion(height_prop);
}
if(m_scroll_view_corner)
{
rgb_color cur_color = m_scroll_view_corner->ViewColor();
rgb_color new_color;
if(active_scroller)
new_color = BeBackgroundGrey;
else
new_color = BeInactiveControlGrey;
if(new_color.red != cur_color.red || new_color.green != cur_color.green ||
new_color.blue != cur_color.blue || new_color.alpha != cur_color.alpha)
{
m_scroll_view_corner->SetViewColor(new_color);
m_scroll_view_corner->Invalidate();
}
}
}

View File

@ -1,78 +0,0 @@
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
//Conventions:
// Global constants (declared with const) and #defines - all uppercase letters with words separated
// by underscores.
// (E.G., #define MY_DEFINE 5).
// (E.G., const int MY_CONSTANT = 5;).
// New data types (classes, structs, typedefs, etc.) - begin with an uppercase letter followed by
// lowercase words separated by uppercase letters. Enumerated constants contain a prefix
// associating them with a particular enumerated set.
// (E.G., typedef int MyTypedef;).
// (E.G., enum MyEnumConst {MEC_ONE, MEC_TWO};)
// Global variables - begin with "g_" followed by lowercase words separated by underscores.
// (E.G., int g_my_global;).
// Argument and local variables - begin with a lowercase letter followed by
// lowercase words separated by underscores.
// (E.G., int my_local;).
// Member variables - begin with "m_" followed by lowercase words separated by underscores.
// (E.G., int m_my_member;).
// Functions (member or global) - begin with an uppercase letter followed by lowercase words
// separated by uppercase letters.
// (E.G., void MyFunction(void);).
#ifndef _SGB_BETTER_SCROLL_VIEW_H_
#define _SGB_BETTER_SCROLL_VIEW_H_
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include <ScrollView.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include "ScrollViewCorner.h"
//******************************************************************************************************
//**** CLASS DECLARATIONS
//******************************************************************************************************
class BetterScrollView : public BScrollView
{
public:
BetterScrollView(const char *name, BView *target, uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP,
uint32 flags = B_FRAME_EVENTS | B_WILL_DRAW, bool horizontal = true, bool vertical = true,
bool scroll_view_corner = true, border_style border = B_FANCY_BORDER);
virtual ~BetterScrollView();
virtual void SetDataRect(BRect data_rect, bool scrolling_allowed = true);
inline BRect DataRect() {return m_data_rect;}
virtual void FrameResized(float new_width, float new_height);
virtual void AttachedToWindow();
private:
void UpdateScrollBars(bool scrolling_allowed);
BRect m_data_rect;
BScrollBar* m_h_scrollbar;
BScrollBar* m_v_scrollbar;
ScrollViewCorner* m_scroll_view_corner;
BView* m_target;
};
#endif

View File

@ -1,426 +0,0 @@
//Column list header source file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <string.h>
#include <Window.h>
#include <Region.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include "CLVColumn.h"
#include "ColumnListView.h"
#include "CLVColumnLabelView.h"
#include "NewStrings.h"
#include "Descending.h"
#include "Ascending.h"
#include "PrefilledBitmap.h"
//******************************************************************************************************
//**** CLVColumn CLASS DEFINITION
//******************************************************************************************************
CLVColumn::CLVColumn(const char* label,float width,uint32 flags,float min_width)
{
if(flags & CLV_EXPANDER)
{
label = NULL;
width = 15.0;
min_width = 15.0;
flags &= CLV_NOT_MOVABLE | CLV_LOCK_AT_BEGINNING | CLV_HIDDEN | CLV_LOCK_WITH_RIGHT;
flags |= CLV_EXPANDER | CLV_NOT_RESIZABLE | CLV_MERGE_WITH_RIGHT;
}
if(min_width < 4.0)
min_width = 4.0;
if(width < min_width)
width = min_width;
if(label)
{
fLabel = new char[strlen(label)+1];
strcpy((char*)fLabel,label);
if(CLV_HEADER_TRUNCATE)
{
int32 truncated_text_length = strlen(label)+3;
fTruncatedText = new char[truncated_text_length];
fTruncatedText[0] = 0;
fCachedRect.Set(-1,-1,-1,-1);
}
else
fTruncatedText = NULL;
}
else
{
fLabel = NULL;
fTruncatedText = NULL;
}
fWidth = width;
fMinWidth = min_width;
fFlags = flags;
fPushedByExpander = false;
fParent = NULL;
fSortMode = NoSort;
}
CLVColumn::~CLVColumn()
{
if(fParent)
fParent->RemoveColumn(this);
if(fLabel)
delete[] fLabel;
if(fTruncatedText)
delete[] fTruncatedText;
}
float CLVColumn::Width() const
{
return fWidth;
}
void CLVColumn::SetWidth(float width)
{
if(width < fMinWidth)
width = fMinWidth;
if(width != fWidth)
{
float OldWidth = fWidth;
fWidth = width;
if(IsShown() && fParent)
{
//Figure out the area after this column to scroll
BRect ColumnViewBounds = fParent->fColumnLabelView->Bounds();
BRect MainViewBounds = fParent->Bounds();
BRect SourceArea = ColumnViewBounds;
float Delta = width-OldWidth;
if(!(fFlags&CLV_RIGHT_JUSTIFIED))
SourceArea.left = fColumnEnd+1.0;
else
{
if(Delta >= 0)
SourceArea.left = fColumnBegin;
else
SourceArea.left = (fColumnBegin-Delta)+1;
}
BRect DestArea = SourceArea;
DestArea.left += Delta;
DestArea.right += Delta;
float LimitShift;
if(DestArea.right > ColumnViewBounds.right)
{
LimitShift = DestArea.right-ColumnViewBounds.right;
DestArea.right -= LimitShift;
SourceArea.right -= LimitShift;
}
if(DestArea.left < ColumnViewBounds.left)
{
LimitShift = ColumnViewBounds.left - DestArea.left;
DestArea.left += LimitShift;
SourceArea.left += LimitShift;
}
//Scroll the area that is being shifted
BWindow* ParentWindow = fParent->Window();
if(ParentWindow)
ParentWindow->UpdateIfNeeded();
fParent->fColumnLabelView->CopyBits(SourceArea,DestArea);
SourceArea.top = MainViewBounds.top;
SourceArea.bottom = MainViewBounds.bottom;
DestArea.top = MainViewBounds.top;
DestArea.bottom = MainViewBounds.bottom;
fParent->CopyBits(SourceArea,DestArea);
//Invalidate the region that got revealed
DestArea = ColumnViewBounds;
if(width > OldWidth)
{
if(!(fFlags&CLV_RIGHT_JUSTIFIED))
{
DestArea.left = fColumnEnd+1.0;
DestArea.right = fColumnEnd+Delta;
}
else
{
DestArea.left = fColumnBegin;
DestArea.right = fColumnBegin+Delta;
}
}
else
{
DestArea.left = ColumnViewBounds.right+Delta+1.0;
DestArea.right = ColumnViewBounds.right;
}
fParent->fColumnLabelView->Invalidate(DestArea);
DestArea.top = MainViewBounds.top;
DestArea.bottom = MainViewBounds.bottom;
fParent->Invalidate(DestArea);
if(fFlags & CLV_HEADER_TRUNCATE)
{
//Do truncation of label
BRect invalid_region = TruncateText(width);
if(fCachedRect != BRect(-1,-1,-1,-1))
fCachedRect.right += Delta;
if(invalid_region != BRect(-1,-1,-1,-1))
{
if(!(fFlags&CLV_RIGHT_JUSTIFIED))
GetHeaderView()->Invalidate(invalid_region);
else
GetHeaderView()->Invalidate(fCachedRect);
}
}
//Invalidate the old or new resize handle as necessary
/*DestArea = ColumnViewBounds;
if(width > OldWidth)
DestArea.left = fColumnEnd;
else
DestArea.left = fColumnEnd + Delta;
DestArea.right = DestArea.left;
fParent->fColumnLabelView->Invalidate(DestArea);
*/
fParent->fColumnLabelView->Invalidate();
//Update the column sizes, positions and group positions
fParent->UpdateColumnSizesDataRectSizeScrollBars(false);
fParent->fColumnLabelView->UpdateDragGroups();
}
if(fParent)
fParent->ColumnWidthChanged(fParent->fColumnList.IndexOf(this),fWidth);
}
}
BRect CLVColumn::TruncateText(float column_width)
//Returns whether the truncated text has changed
{
column_width -= 1+8+5+1;
//Because when I draw the text I start drawing 8 pixels to the right from the text area's left edge,
//which is in turn 1 pixel smaller than the column at each edge, and I want 5 trailing pixels.
BRect invalid(-1,-1,-1,-1);
if(fParent == NULL)
return invalid;
const char* text = GetLabel();
char new_text[256];
BFont font;
fParent->GetFont(&font);
GetTruncatedString(text,new_text,column_width,256,&font);
if(strcmp(fTruncatedText,new_text)!=0)
{
//The truncated text has changed
invalid = fCachedRect;
if(invalid != BRect(-1,-1,-1,-1))
{
//Figure out which region just got changed
int32 cmppos;
int32 cmplen = strlen(new_text);
char remember = 0;
for(cmppos = 0; cmppos <= cmplen; cmppos++)
if(new_text[cmppos] != fTruncatedText[cmppos])
{
remember = new_text[cmppos];
new_text[cmppos] = 0;
break;
}
invalid.left += 8 + be_plain_font->StringWidth(new_text);
new_text[cmppos] = remember;
}
//Remember the new truncated text
strcpy(fTruncatedText,new_text);
}
return invalid;
}
void GetTruncatedString(const char* full_string, char* truncated, float width, int32 truncate_buf_size,
const BFont* font)
{
Strtcpy(truncated,full_string,truncate_buf_size);
int32 choppos = strlen(truncated)-1;
while(choppos >= -2 && font->StringWidth(truncated) > width)
{
while(choppos > 0 && truncated[choppos-1] == ' ')
choppos--;
if(choppos > 0 || (choppos == 0 && truncated[0] == ' '))
truncated[choppos] = '.';
if(choppos > -1)
truncated[choppos+1] = '.';
if(choppos > -2)
truncated[choppos+2] = '.';
truncated[choppos+3] = 0;
choppos--;
}
}
uint32 CLVColumn::Flags() const
{
return fFlags;
}
bool CLVColumn::IsShown() const
{
if(fFlags & CLV_HIDDEN)
return false;
else
return true;
}
void CLVColumn::SetShown(bool Shown)
{
bool shown = IsShown();
if(shown != Shown)
{
if(Shown)
fFlags &= 0xFFFFFFFF^CLV_HIDDEN;
else
fFlags |= CLV_HIDDEN;
if(fParent)
{
float UpdateLeft = fColumnBegin;
fParent->UpdateColumnSizesDataRectSizeScrollBars();
fParent->fColumnLabelView->UpdateDragGroups();
if(Shown)
UpdateLeft = fColumnBegin;
BRect Area = fParent->fColumnLabelView->Bounds();
Area.left = UpdateLeft;
fParent->fColumnLabelView->Invalidate(Area);
Area = fParent->Bounds();
Area.left = UpdateLeft;
fParent->Invalidate(Area);
if(fFlags & CLV_EXPANDER)
{
if(!Shown)
fParent->fExpanderColumn = -1;
else
fParent->fExpanderColumn = fParent->IndexOfColumn(this);
}
}
}
}
CLVSortMode CLVColumn::SortMode() const
{
return fSortMode;
}
void CLVColumn::SetSortMode(CLVSortMode mode)
{
if(fParent)
fParent->SetSortMode(fParent->IndexOfColumn(this),mode);
else
fSortMode = mode;
}
const char* CLVColumn::GetLabel() const
{
return fLabel;
}
ColumnListView* CLVColumn::GetParent() const
{
return fParent;
}
BView* CLVColumn::GetHeaderView() const
{
if(fParent)
return fParent->fColumnLabelView;
else
return NULL;
}
void CLVColumn::DrawColumnHeader(BView* view, BRect header_rect, bool sort_key, bool focus,
float font_ascent)
{
char* label;
if(fFlags & CLV_HEADER_TRUNCATE)
{
if(fCachedRect == BRect(-1,-1,-1,-1))
{
//Have never drawn it before
TruncateText(header_rect.right-header_rect.left);
}
label = fTruncatedText;
}
else
label = fLabel;
if(label)
{
if(focus)
view->SetHighColor(BeFocusBlue);
else
view->SetHighColor(Black);
//Draw the label
view->SetDrawingMode(B_OP_OVER);
BPoint text_point;
if(!(fFlags&CLV_RIGHT_JUSTIFIED))
text_point.Set(header_rect.left+8.0,header_rect.top+1.0+font_ascent);
else
{
BFont label_font;
view->GetFont(&label_font);
float string_width = label_font.StringWidth(label);
text_point.Set(header_rect.right-8.0-string_width,header_rect.top+1.0+font_ascent);
}
view->DrawString(label,text_point);
view->SetDrawingMode(B_OP_COPY);
//Underline if this is a selected sort column
if(sort_key)
{
PrefilledBitmap *bitmap = NULL;
switch(fSortMode)
{
case Ascending:
bitmap = new PrefilledBitmap(BRect(0,0,8,15),B_CMAP8,kAscendingIconBits);
break;
case Descending:
bitmap = new PrefilledBitmap(BRect(0,0,8,15),B_CMAP8,kDescendingIconBits);
break;
}
float Width = view->StringWidth(label);
view->StrokeLine(BPoint(text_point.x-1,text_point.y+2.0),
BPoint(text_point.x-1+Width,text_point.y+2.0));
if(bitmap && header_rect.Width() > 10+20)
{
view->SetDrawingMode(B_OP_OVER);
BRect iconBounds = header_rect;
iconBounds.left= iconBounds.right - 8;
BRegion region;
region.Include(iconBounds);
view->ConstrainClippingRegion(&region);
view->DrawBitmap(bitmap,iconBounds);
}
delete bitmap;
}
fCachedRect = header_rect;
}
}

View File

@ -1,161 +0,0 @@
//Column list header header file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#ifndef _CLV_COLUMN_H_
#define _CLV_COLUMN_H_
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <SupportDefs.h>
#include <Rect.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
//******************************************************************************************************
class ColumnListView;
class CLVColumn;
class CLVListItem;
//******************************************************************************************************
//**** CONSTANTS
//******************************************************************************************************
//Flags
enum
{
CLV_SORT_KEYABLE = 0x00000001, //Can be used as the sorting key
CLV_NOT_MOVABLE = 0x00000002, //Column can't be moved by user
CLV_NOT_RESIZABLE = 0x00000004, //Column can't be resized by user
CLV_LOCK_AT_BEGINNING = 0x00000008, //Movable columns may not be placed or moved by the user
//into a position before this one
CLV_LOCK_AT_END = 0x00000010, //Movable columns may not be placed or moved by the user
//into a position after this one
CLV_HIDDEN = 0x00000020, //This column is hidden initially
CLV_MERGE_WITH_RIGHT = 0x00000040, //Merge this column label with the one that follows it.
CLV_LOCK_WITH_RIGHT = 0x00000080, //Lock this column to the one that follows it such that
//if the column to the right is moved by the user, this
//one will move with it and vice versa
CLV_EXPANDER = 0x00000100, //Column contains an expander. You may only use one
//expander in a ColumnListView, and an expander may not be
//added to a non-hierarchal ColumnListView. It may not
//have a label. Its width is automatically set to 20.0.
//The only flags that affect it are CLV_NOT_MOVABLE,
//CLV_LOCK_AT_BEGINNING, CLV_NOT_SHOWN and
//CLV_LOCK_WITH_RIGHT. The others are set for you:
//CLV_NOT_RESIZABLE | CLV_MERGE_WITH_RIGHT
CLV_PUSH_PASS = 0x00000200, //Causes this column, if pushed by an expander to the
//left, to pass that push on and also push the next
//column to the right.
CLV_HEADER_TRUNCATE = 0x00000400, //Causes this column label to be tructated with an ellipsis
//if the column header is narrower than the text it contains.
CLV_TELL_ITEMS_WIDTH = 0x00000800, //Causes items in this column to be informed when the column
//width is changed. This is necessary for CLVEasyItems.
CLV_RIGHT_JUSTIFIED = 0x00001000 //Causes the column, when resized, to shift its content,
//not just the content of subsequent columns. This does not
//affect the rendering of content in items in the column,
//just the area that gets scrolled.
};
enum CLVSortMode
{
Ascending,
Descending,
NoSort
};
//******************************************************************************************************
//**** FUNCTIONS
//******************************************************************************************************
void GetTruncatedString(const char* full_string, char* truncated, float width, int32 truncate_buf_size,
const BFont* font);
//******************************************************************************************************
//**** ColumnListView CLASS DECLARATION
//******************************************************************************************************
class CLVColumn
{
public:
//Constructor and destructor
CLVColumn( const char* label,
float width = 20.0,
uint32 flags = 0,
float min_width = 20.0);
virtual ~CLVColumn();
//Archival stuff
/* Not implemented yet
CLVColumn(BMessage* archive);
static CLVColumn* Instantiate(BMessage* data);
virtual status_t Archive(BMessage* data, bool deep = true) const;
*/
//Functions
float Width() const;
virtual void SetWidth(float width); //Can be overridden to detect changes to the column width
//however since you are probably overriding
//ColumnListView and dealing with an array of columns
//anyway, it is probably more useful to override
//ColumnListView::ColumnWidthChanged to detect changes to
//column widths
uint32 Flags() const;
bool IsShown() const;
virtual void SetShown(bool shown);
CLVSortMode SortMode() const;
virtual void SetSortMode(CLVSortMode mode);
const char* GetLabel() const;
ColumnListView* GetParent() const ;
BView* GetHeaderView() const;
virtual void DrawColumnHeader(BView* view, BRect header_rect, bool sort_key, bool focus,
float font_ascent);
//Can be overridden to implement your own column header drawing, for example if you want to do
//string truncation.
//- The background will already be filled with and LowColor set to BeBackgroundGrey
//- The highlight and shadow edges will already be drawn
//- The header_rect does not include the one-pixel border for the highlight and shadow edges.
//- The view font will already be set to the font specified when the ColumnListView was
// constructed, and should not be changed
//- If text is being rendered, it should be rendered at
// BPoint text_point(header_rect.left+8.0,header_rect.top+1.0+font_ascent)
//- If sort_key is true, the text should be underlined, with the underline being drawn from
// BPoint(text_point.x-1,text_point.y+2.0) to BPoint(text_point.x-1+label_width,text_point.y+2.0)
//- If focus is true, the text and underline should be in BeFocusBlue, otherwise in Black.
private:
friend class ColumnListView;
friend class CLVColumnLabelView;
friend class CLVListItem;
BRect TruncateText(float column_width);
char *fLabel;
char* fTruncatedText;
BRect fCachedRect;
float fWidth;
float fMinWidth;
float fColumnBegin;
float fColumnEnd;
uint32 fFlags;
bool fPushedByExpander;
CLVSortMode fSortMode;
ColumnListView* fParent;
};
#endif

View File

@ -1,788 +0,0 @@
//ColumnLabelView class source file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include <Region.h>
#include <Application.h>
#include <Window.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include "CLVColumnLabelView.h"
#include "ColumnListView.h"
#include "CLVColumn.h"
#include "Cursors.h"
//******************************************************************************************************
//**** FUNCTION DEFINITIONS
//******************************************************************************************************
CLVColumnLabelView::CLVColumnLabelView(BRect Bounds,ColumnListView* parent,const BFont* Font)
: BView(Bounds,NULL,B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP,B_WILL_DRAW|B_FRAME_EVENTS),
fDragGroups(10)
{
SetFont(Font);
SetViewColor(BeBackgroundGrey);
SetLowColor(BeBackgroundGrey);
SetHighColor(Black);
fParent = parent;
fDisplayList = &fParent->fColumnDisplayList;
fColumnClicked = NULL;
fColumnDragging = false;
fColumnResizing = false;
fModifiedCursor = false;
font_height FontAttributes;
Font->GetHeight(&FontAttributes);
fFontAscent = ceil(FontAttributes.ascent);
}
CLVColumnLabelView::~CLVColumnLabelView()
{
int32 NumberOfGroups = fDragGroups.CountItems();
for(int32 Counter = 0; Counter < NumberOfGroups; Counter++)
fDragGroups.RemoveItem(int32(0));
}
void CLVColumnLabelView::Draw(BRect update_rect)
{
BRect ViewBounds = Bounds();
//Draw each column label in turn
float ColumnBegin = 0.0;
float ColumnEnd = -1.0;
bool MergeWithLeft = false;
int32 NumberOfColumns = fDisplayList->CountItems();
BPoint Start,Stop;
for(int32 ColumnDraw = 0; ColumnDraw < NumberOfColumns; ColumnDraw++)
{
CLVColumn* ThisColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnDraw);
if(ThisColumn->IsShown())
{
//Figure out where this column is
ColumnBegin = ThisColumn->fColumnBegin;
ColumnEnd = ThisColumn->fColumnEnd;
//Start by figuring out if this column will merge with a shown column to the right
bool MergeWithRight = false;
if(ThisColumn->fFlags & CLV_MERGE_WITH_RIGHT)
{
for(int32 ColumnCounter = ColumnDraw+1; ColumnCounter < NumberOfColumns;
ColumnCounter++)
{
CLVColumn* NextColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnCounter);
if(NextColumn->IsShown())
{
//The next column is shown
MergeWithRight = true;
break;
}
else if(!(NextColumn->fFlags & CLV_MERGE_WITH_RIGHT))
//The next column is not shown and doesn't pass on the merge
break;
}
}
if(update_rect.Intersects(BRect(ColumnBegin,ViewBounds.top,ColumnEnd,
ViewBounds.bottom)))
{
//Need to draw this column
BeginLineArray(4);
//Top line
Start.Set(ColumnBegin,ViewBounds.top);
Stop.Set(ColumnEnd-1.0,ViewBounds.top);
if(MergeWithRight && !(ThisColumn == fColumnClicked && fColumnResizing))
Stop.x = ColumnEnd;
AddLine(Start,Stop,BeHighlight);
//Left line
if(!MergeWithLeft)
AddLine(BPoint(ColumnBegin,ViewBounds.top+1.0),
BPoint(ColumnBegin,ViewBounds.bottom),BeHighlight);
//Bottom line
Start.Set(ColumnBegin+1.0,ViewBounds.bottom);
if(MergeWithLeft)
Start.x = ColumnBegin;
Stop.Set(ColumnEnd-1.0,ViewBounds.bottom);
if(MergeWithRight && !(ThisColumn == fColumnClicked && fColumnResizing))
Stop.x = ColumnEnd;
AddLine(Start,Stop,BeShadow);
//Right line
if(ThisColumn == fColumnClicked && fColumnResizing)
AddLine(BPoint(ColumnEnd,ViewBounds.top),BPoint(ColumnEnd,ViewBounds.bottom),
BeFocusBlue);
else if(!MergeWithRight)
AddLine(BPoint(ColumnEnd,ViewBounds.top),BPoint(ColumnEnd,ViewBounds.bottom),
BeShadow);
EndLineArray();
//Add the label
//Limit the clipping region to the interior of the box
BRect TextRect(ColumnBegin+1.0,ViewBounds.top+1.0,ColumnEnd-1.0,
ViewBounds.bottom-1.0);
BRegion TextRegion;
TextRegion.Include(TextRect);
ConstrainClippingRegion(&TextRegion);
bool focus;
bool sort_key;
if(ThisColumn == fColumnClicked && !fColumnResizing)
focus = true;
else
focus = false;
if(fParent->fSortKeyList.HasItem(ThisColumn) && ThisColumn->fSortMode != NoSort)
sort_key = true;
else
sort_key = false;
ThisColumn->DrawColumnHeader(this,TextRect,sort_key,focus,fFontAscent);
//Restore the clipping region
ConstrainClippingRegion(NULL);
}
//Set MergeWithLeft flag for the next column to the appropriate state
MergeWithLeft = MergeWithRight;
}
}
//Add highlight and shadow to the region after the columns if necessary
if(ColumnEnd < ViewBounds.right)
{
ColumnBegin = ColumnEnd+1.0;
if(update_rect.Intersects(BRect(ColumnEnd+1.0,ViewBounds.top,ViewBounds.right,
ViewBounds.bottom)))
{
BeginLineArray(3);
//Top line
AddLine(BPoint(ColumnBegin,ViewBounds.top),BPoint(ViewBounds.right,ViewBounds.top),
BeHighlight);
//Left line
AddLine(BPoint(ColumnBegin,ViewBounds.top+1.0),BPoint(ColumnBegin,ViewBounds.bottom),
BeHighlight);
//Bottom line
Start.Set(ColumnBegin+1.0,ViewBounds.bottom);
if(MergeWithLeft)
Start.x = ColumnBegin;
Stop.Set(ViewBounds.right,ViewBounds.bottom);
AddLine(Start,Stop,BeShadow);
EndLineArray();
}
}
//Draw the dragging box if necessary
if(fColumnClicked && fColumnDragging)
{
float DragOutlineLeft = fPreviousMousePos.x-fDragBoxMouseHoldOffset;
float GroupBegin = ((CLVDragGroup*)fDragGroups.ItemAt(fDragGroup))->GroupBegin;
if(DragOutlineLeft < GroupBegin && fSnapGroupBefore == -1)
DragOutlineLeft = GroupBegin;
if(DragOutlineLeft > GroupBegin && fSnapGroupAfter == -1)
DragOutlineLeft = GroupBegin;
float DragOutlineRight = DragOutlineLeft + fDragBoxWidth;
BeginLineArray(4);
AddLine(BPoint(DragOutlineLeft,ViewBounds.top),BPoint(DragOutlineRight,
ViewBounds.top),BeFocusBlue);
AddLine(BPoint(DragOutlineLeft,ViewBounds.bottom),BPoint(DragOutlineRight,
ViewBounds.bottom),BeFocusBlue);
AddLine(BPoint(DragOutlineLeft,ViewBounds.top+1.0),BPoint(DragOutlineLeft,
ViewBounds.bottom-1.0),BeFocusBlue);
AddLine(BPoint(DragOutlineRight,ViewBounds.top+1.0),BPoint(DragOutlineRight,
ViewBounds.bottom-1.0),BeFocusBlue);
EndLineArray();
fPrevDragOutlineLeft = DragOutlineLeft;
fPrevDragOutlineRight = DragOutlineRight;
}
}
void CLVColumnLabelView::MouseDown(BPoint Point)
{
//Only pay attention to primary mouse button
bool WatchMouse = false;
BPoint MousePos;
uint32 Buttons;
GetMouse(&MousePos,&Buttons);
if(Buttons == B_PRIMARY_MOUSE_BUTTON)
{
BRect ViewBounds = Bounds();
//Make sure no other column was already clicked. If so, just discard the old one and redraw the
//view
if(fColumnClicked != NULL)
{
Invalidate();
fColumnClicked = NULL;
}
//Find the column that the user clicked, if any
bool GrabbedResizeTab = false;
int32 NumberOfColumns = fDisplayList->CountItems();
int32 ColumnFind;
CLVColumn* ThisColumn = NULL;
for(ColumnFind = 0; ColumnFind < NumberOfColumns; ColumnFind++)
{
ThisColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
if(ThisColumn->IsShown())
{
float ColumnBegin = ThisColumn->fColumnBegin;
float ColumnEnd = ThisColumn->fColumnEnd;
if(Point.x >= ColumnBegin && Point.x <= ColumnEnd)
{
//User clicked in this column
if(Point.x <= ColumnBegin+2.0)
{
//User clicked the resize tab preceding this column
for(ColumnFind--; ColumnFind >= 0; ColumnFind--)
{
ThisColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
if(ThisColumn->IsShown())
{
GrabbedResizeTab = true;
break;
}
}
}
else if(Point.x >= ColumnEnd-2.0)
{
//User clicked the resize tab for (after) this column
GrabbedResizeTab = true;
}
else
{
//The user clicked in this column
fColumnClicked = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
fColumnResizing = false;
fPreviousMousePos = Point;
fMouseClickedPos = Point;
fColumnDragging = false;
SetSnapMinMax();
fDragBoxMouseHoldOffset = Point.x-
((CLVDragGroup*)fDragGroups.ItemAt(fDragGroup))->GroupBegin;
Invalidate(BRect(ColumnBegin+1.0,ViewBounds.top+1.0,ColumnEnd-1.0,
ViewBounds.bottom-1.0));
//Start watching the mouse
WatchMouse = true;
}
break;
}
}
}
if(GrabbedResizeTab)
{
//The user grabbed a resize tab. See if resizing of this column is allowed
if(!(ThisColumn->fFlags & CLV_NOT_RESIZABLE))
{
fColumnClicked = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
fColumnResizing = true;
fPreviousMousePos = Point;
fMouseClickedPos = Point;
fColumnDragging = false;
fResizeMouseHoldOffset = Point.x-fColumnClicked->fColumnEnd;
Invalidate(BRect(fColumnClicked->fColumnEnd,ViewBounds.top,ThisColumn->fColumnEnd,
ViewBounds.bottom));
//Start watching the mouse
WatchMouse = true;
}
}
}
if(WatchMouse)
SetMouseEventMask(B_POINTER_EVENTS,B_NO_POINTER_HISTORY);
fPreviousMousePos = MousePos;
}
void CLVColumnLabelView::MouseMoved(BPoint where, uint32 code, const BMessage *message)
{
bool should_show_modified_cursor = false;
if(fColumnClicked == NULL)
{
if(code != B_EXITED_VIEW)
{
//Check for whether to switch the mouse to indicate that you can resize
int32 NumberOfColumns = fDisplayList->CountItems();
for(int32 ColumnFind = 0; ColumnFind < NumberOfColumns; ColumnFind++)
{
CLVColumn* ThisColumn = (CLVColumn*)fDisplayList->ItemAt(ColumnFind);
if(ThisColumn->IsShown())
{
float ColumnEnd = ThisColumn->fColumnEnd;
if(where.x >= ColumnEnd-2.0 && where.x <= ColumnEnd+2.0)
{
//User clicked the resize tab for (after) this column
if(!(ThisColumn->fFlags & CLV_NOT_RESIZABLE))
should_show_modified_cursor = true;
break;
}
else if(where.x < ColumnEnd+2.0)
break;
}
}
}
}
else if(!fColumnResizing)
{
//User is clicking or dragging
BRect ViewBounds = Bounds();
if((where.x<fMouseClickedPos.x-2.0 || where.x>fMouseClickedPos.x+2.0) &&
!fColumnDragging)
{
//User is initiating a drag
if(fTheDragGroup->Flags & CLV_NOT_MOVABLE)
{
//Not allowed to drag this column - terminate the click
Invalidate(BRect(fColumnClicked->fColumnBegin,ViewBounds.top,
fColumnClicked->fColumnEnd,ViewBounds.bottom));
fColumnClicked = NULL;
}
else
{
//Actually initiate a drag
fColumnDragging = true;
fPrevDragOutlineLeft = -1.0;
fPrevDragOutlineRight = -1.0;
}
}
//Now deal with dragging
if(fColumnDragging)
{
//User is dragging
if(where.x<fPreviousMousePos.x || where.x>fPreviousMousePos.x)
{
//Mouse moved since I last checked
ViewBounds = Bounds();
bool ColumnSnapped;
do
{
//Live dragging of columns
ColumnSnapped = false;
float ColumnsUpdateLeft = 0.0;
float ColumnsUpdateRight = 0.0;
float MainViewUpdateLeft = 0.0;
float MainViewUpdateRight = 0.0;
CLVColumn* LastSwapColumn = NULL;
if(fSnapMin != -1.0 && where.x < fSnapMin)
{
//Shift the group left
ColumnsUpdateLeft = fTheShownGroupBefore->GroupBegin;
ColumnsUpdateRight = fTheDragGroup->GroupEnd;
MainViewUpdateLeft = ColumnsUpdateLeft;
MainViewUpdateRight = ColumnsUpdateRight;
LastSwapColumn = fTheShownGroupBefore->LastColumnShown;
if(fTheDragGroup->LastColumnShown->fFlags & CLV_MERGE_WITH_RIGHT)
ColumnsUpdateRight += 1.0;
else if(fTheShownGroupBefore->LastColumnShown->fFlags & CLV_MERGE_WITH_RIGHT)
ColumnsUpdateRight += 1.0;
ShiftDragGroup(fSnapGroupBefore);
ColumnSnapped = true;
}
if(fSnapMax != -1.0 && where.x > fSnapMax)
{
//Shift the group right
ColumnsUpdateLeft = fTheDragGroup->GroupBegin;
ColumnsUpdateRight = fTheShownGroupAfter->GroupEnd;
MainViewUpdateLeft = ColumnsUpdateLeft;
MainViewUpdateRight = ColumnsUpdateRight;
LastSwapColumn = fTheDragGroup->LastColumnShown;
if(fTheDragGroup->LastColumnShown->fFlags & CLV_MERGE_WITH_RIGHT)
ColumnsUpdateRight += 1.0;
else if(fTheShownGroupAfter->LastColumnShown->fFlags & CLV_MERGE_WITH_RIGHT)
ColumnsUpdateRight += 1.0;
ShiftDragGroup(fSnapGroupAfter+1);
ColumnSnapped = true;
}
if(ColumnSnapped)
{
//Redraw the snapped column labels
Invalidate(BRect(ColumnsUpdateLeft,ViewBounds.top,ColumnsUpdateRight,
ViewBounds.bottom));
BRect MainViewBounds = fParent->Bounds();
//Modify MainViewUpdateRight if more columns are pushed by expanders
if(LastSwapColumn->fFlags & CLV_EXPANDER ||
(LastSwapColumn->fPushedByExpander && (LastSwapColumn->fFlags &
CLV_PUSH_PASS)))
{
int32 NumberOfColumns = fDisplayList->CountItems();
for(int32 ColumnCounter = fDisplayList->IndexOf(LastSwapColumn)+1;
ColumnCounter < NumberOfColumns; ColumnCounter++)
{
CLVColumn* ThisColumn =
(CLVColumn*)fDisplayList->ItemAt(ColumnCounter);
if(ThisColumn->IsShown())
{
if(ThisColumn->fPushedByExpander)
MainViewUpdateRight = ThisColumn->fColumnEnd;
else
break;
}
}
}
fParent->Invalidate(BRect(MainViewUpdateLeft,MainViewBounds.top,
MainViewUpdateRight,MainViewBounds.bottom));
}
}while(ColumnSnapped);
//Erase and redraw the drag rectangle but not the interior to avoid label flicker
float Min = fPrevDragOutlineLeft;
float Max = fPrevDragOutlineRight;
float Min2 = where.x-fDragBoxMouseHoldOffset;
float GroupBegin = ((CLVDragGroup*)fDragGroups.ItemAt(fDragGroup))->GroupBegin;
if(Min2 < GroupBegin && fSnapGroupBefore == -1)
Min2 = GroupBegin;
if(Min2 > GroupBegin && fSnapGroupAfter == -1)
Min2 = GroupBegin;
float Max2 = Min2 + fDragBoxWidth;
float Temp;
if(Min2 < Min || Min == -1.0)
{Temp = Min2;Min2 = Min;Min = Temp;}
if(Max2 > Max || Max == -1.0)
{Temp = Max2;Max2 = Max;Max = Temp;}
Invalidate(BRect(Min,ViewBounds.top+1.0,Min,ViewBounds.bottom-1.0));
if(Min2 != -1.0)
Invalidate(BRect(Min2,ViewBounds.top+1.0,Min2,ViewBounds.bottom-1.0));
Invalidate(BRect(Max,ViewBounds.top+1.0,Max,ViewBounds.bottom-1.0));
if(Max2 != -1.0)
Invalidate(BRect(Max2,ViewBounds.top+1.0,Max2,ViewBounds.bottom-1.0));
Invalidate(BRect(Min,ViewBounds.top,Max,ViewBounds.top));
Invalidate(BRect(Min,ViewBounds.bottom,Max,ViewBounds.bottom));
}
}
}
else
{
//User is resizing the column
if(where.x<fPreviousMousePos.x || where.x>fPreviousMousePos.x)
{
float NewWidth = where.x - fResizeMouseHoldOffset - fColumnClicked->fColumnBegin;
if(NewWidth < fColumnClicked->fMinWidth)
NewWidth = fColumnClicked->fMinWidth;
if(NewWidth != fColumnClicked->fWidth)
fColumnClicked->SetWidth(NewWidth);
Invalidate();
}
should_show_modified_cursor = true;
}
fPreviousMousePos = where;
if(fModifiedCursor && !should_show_modified_cursor)
{
be_app->SetCursor(B_HAND_CURSOR);
be_app->ShowCursor();
}
if(should_show_modified_cursor && !fModifiedCursor)
{
be_app->SetCursor(c_v_resize_cursor);
be_app->ShowCursor();
}
fModifiedCursor = should_show_modified_cursor;
}
void CLVColumnLabelView::MouseUp(BPoint where)
{
if(fColumnClicked == NULL)
return;
BRect ViewBounds = Bounds();
if(!fColumnDragging && !fColumnResizing)
{
//Column was clicked
uint32 ColumnFlags = fColumnClicked->Flags();
if(ColumnFlags&CLV_SORT_KEYABLE)
{
//The column is a "sortable" column
uint32 Modifiers;
Window()->CurrentMessage()->FindInt32("modifiers",(int32*)&Modifiers);
if(!(Modifiers&B_SHIFT_KEY))
{
//The user wants to select it as the main sorting column
if(fParent->fSortKeyList.ItemAt(0) == fColumnClicked)
//The column was already selected; switch sort modes
fParent->ReverseSortMode(fParent->fColumnList.IndexOf(fColumnClicked));
else
//The user selected this column for sorting
fParent->SetSortKey(fParent->fColumnList.IndexOf(fColumnClicked));
}
else
{
//The user wants to add it as a secondary sorting column
if(fParent->fSortKeyList.HasItem(fColumnClicked))
//The column was already selected; switch sort modes
fParent->ReverseSortMode(fParent->fColumnList.IndexOf(fColumnClicked));
else
//The user selected this column for sorting
fParent->AddSortKey(fParent->fColumnList.IndexOf(fColumnClicked));
}
}
}
else if(fColumnDragging)
{
//Column was dragging; erase the drag box but not the interior to avoid label flicker
Invalidate(BRect(fPrevDragOutlineLeft,ViewBounds.top+1.0,
fPrevDragOutlineLeft,ViewBounds.bottom-1.0));
Invalidate(BRect(fPrevDragOutlineRight,ViewBounds.top+1.0,
fPrevDragOutlineRight,ViewBounds.bottom-1.0));
Invalidate(BRect(fPrevDragOutlineLeft,ViewBounds.top,
fPrevDragOutlineRight,ViewBounds.top));
Invalidate(BRect(fPrevDragOutlineLeft,ViewBounds.bottom,
fPrevDragOutlineRight,ViewBounds.bottom));
}
else
//Column was resizing; erase the drag tab
Invalidate(BRect(fColumnClicked->fColumnEnd,ViewBounds.top,fColumnClicked->fColumnEnd,
ViewBounds.bottom));
//Unhighlight the label and forget the column
Invalidate(BRect(fColumnClicked->fColumnBegin+1.0,ViewBounds.top+1.0,
fColumnClicked->fColumnEnd-1.0,ViewBounds.bottom-1.0));
fColumnClicked = NULL;
fColumnDragging = false;
fColumnResizing = false;
if(fModifiedCursor)
{
be_app->SetCursor(B_HAND_CURSOR);
be_app->ShowCursor();
fModifiedCursor = false;
}
}
void CLVColumnLabelView::ShiftDragGroup(int32 NewPos)
//Shift the drag group into a new position
{
int32 NumberOfGroups = fDragGroups.CountItems();
int32 GroupCounter;
CLVDragGroup* ThisGroup;
int32 NumberOfColumnsInGroup;
int32 ColumnCounter;
BList NewDisplayList;
//Copy the groups up to the new position
for(GroupCounter = 0; GroupCounter < NewPos; GroupCounter++)
{
if(GroupCounter != fDragGroup)
{
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(GroupCounter);
NumberOfColumnsInGroup = ThisGroup->GroupStopDispListIndex -
ThisGroup->GroupStartDispListIndex + 1;
for(ColumnCounter = ThisGroup->GroupStartDispListIndex; ColumnCounter <=
ThisGroup->GroupStopDispListIndex; ColumnCounter++)
NewDisplayList.AddItem(fDisplayList->ItemAt(ColumnCounter));
}
}
//Copy the group into the new position
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(fDragGroup);
NumberOfColumnsInGroup = ThisGroup->GroupStopDispListIndex - ThisGroup->GroupStartDispListIndex + 1;
for(ColumnCounter = ThisGroup->GroupStartDispListIndex; ColumnCounter <=
ThisGroup->GroupStopDispListIndex; ColumnCounter++)
NewDisplayList.AddItem(fDisplayList->ItemAt(ColumnCounter));
//Copy the rest of the groups, but skip the dragging group
for(GroupCounter = NewPos; GroupCounter < NumberOfGroups; GroupCounter++)
{
if(GroupCounter != fDragGroup)
{
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(GroupCounter);
NumberOfColumnsInGroup = ThisGroup->GroupStopDispListIndex -
ThisGroup->GroupStartDispListIndex + 1;
for(ColumnCounter = ThisGroup->GroupStartDispListIndex; ColumnCounter <=
ThisGroup->GroupStopDispListIndex; ColumnCounter++)
NewDisplayList.AddItem(fDisplayList->ItemAt(ColumnCounter));
}
}
//Set the new order
*fDisplayList = NewDisplayList;
//Update columns and drag groups
fParent->UpdateColumnSizesDataRectSizeScrollBars();
UpdateDragGroups();
SetSnapMinMax();
//Inform the program that the display order changed
int32* NewOrder = new int32[fParent->CountColumns()];
fParent->GetDisplayOrder(NewOrder);
fParent->DisplayOrderChanged(NewOrder);
delete[] NewOrder;
}
void CLVColumnLabelView::UpdateDragGroups()
{
//Make a copy of the DragGroups list. Use it to store the CLVDragGroup's for recycling
BList TempList(fDragGroups);
fDragGroups.MakeEmpty();
int32 NumberOfColumns = fDisplayList->CountItems();
bool ContinueGroup = false;
CLVDragGroup* CurrentGroup = NULL;
for(int32 Counter = 0; Counter < NumberOfColumns; Counter++)
{
CLVColumn* CurrentColumn = (CLVColumn*)fDisplayList->ItemAt(Counter);
if(!ContinueGroup)
{
//Recycle or obtain a new CLVDragGroup
CurrentGroup = (CLVDragGroup*)TempList.RemoveItem(int32(0));
if(CurrentGroup == NULL)
CurrentGroup = new CLVDragGroup;
//Add the CLVDragGroup to the DragGroups list
fDragGroups.AddItem(CurrentGroup);
//Set up the new DragGroup
CurrentGroup->GroupStartDispListIndex = Counter;
CurrentGroup->GroupStopDispListIndex = Counter;
CurrentGroup->Flags = 0;
if(CurrentColumn->IsShown())
{
CurrentGroup->GroupBegin = CurrentColumn->fColumnBegin;
CurrentGroup->GroupEnd = CurrentColumn->fColumnEnd;
CurrentGroup->LastColumnShown = CurrentColumn;
CurrentGroup->Shown = true;
if(CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING)
CurrentGroup->AllLockBeginning = true;
else
CurrentGroup->AllLockBeginning = false;
if(CurrentColumn->fFlags & CLV_LOCK_AT_END)
CurrentGroup->AllLockEnd = true;
else
CurrentGroup->AllLockEnd = false;
}
else
{
CurrentGroup->GroupBegin = -1.0;
CurrentGroup->GroupEnd = -1.0;
CurrentGroup->LastColumnShown = NULL;
CurrentGroup->Shown = false;
if(CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING)
CurrentGroup->AllLockBeginning = true;
else
CurrentGroup->AllLockBeginning = false;
if(CurrentColumn->fFlags & CLV_LOCK_AT_END)
CurrentGroup->AllLockEnd = true;
else
CurrentGroup->AllLockEnd = false;
}
}
else
{
//Add this column to the current DragGroup
CurrentGroup->GroupStopDispListIndex = Counter;
if(CurrentColumn->IsShown())
{
if(CurrentGroup->GroupBegin == -1.0)
CurrentGroup->GroupBegin = CurrentColumn->fColumnBegin;
CurrentGroup->GroupEnd = CurrentColumn->fColumnEnd;
CurrentGroup->LastColumnShown = CurrentColumn;
CurrentGroup->Shown = true;
}
if(!(CurrentColumn->fFlags & CLV_LOCK_AT_BEGINNING))
CurrentGroup->AllLockBeginning = false;
if(!(CurrentColumn->fFlags & CLV_LOCK_AT_END))
CurrentGroup->AllLockEnd = false;
}
CurrentGroup->Flags |= CurrentColumn->fFlags & (CLV_NOT_MOVABLE|CLV_LOCK_AT_BEGINNING|
CLV_LOCK_AT_END);
//See if I should add more columns to this group
if(CurrentColumn->fFlags & CLV_LOCK_WITH_RIGHT)
ContinueGroup = true;
else
ContinueGroup = false;
}
//If any unused groups remain in TempList, delete them
while((CurrentGroup = (CLVDragGroup*)TempList.RemoveItem(int32(0))) != NULL)
delete CurrentGroup;
}
void CLVColumnLabelView::SetSnapMinMax()
{
//Find the column group that the user is dragging and the shown group before it
int32 NumberOfGroups = fDragGroups.CountItems();
int32 ColumnCount;
fDragGroup = -1;
fTheShownGroupBefore = NULL;
fSnapGroupBefore = -1;
CLVDragGroup* ThisGroup;
int32 GroupCounter;
for(GroupCounter = 0; GroupCounter < NumberOfGroups; GroupCounter++)
{
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(GroupCounter);
for(ColumnCount = ThisGroup->GroupStartDispListIndex; ColumnCount <=
ThisGroup->GroupStopDispListIndex; ColumnCount++)
if(fDisplayList->ItemAt(ColumnCount) == fColumnClicked)
{
fDragGroup = GroupCounter;
fTheDragGroup = ThisGroup;
break;
}
if(fDragGroup != -1)
break;
else if(ThisGroup->Shown)
{
fTheShownGroupBefore = ThisGroup;
fSnapGroupBefore = GroupCounter;
}
}
//Find the position of shown group after the one that the user is dragging
fTheShownGroupAfter = NULL;
fSnapGroupAfter = -1;
for(GroupCounter = fDragGroup+1; GroupCounter < NumberOfGroups; GroupCounter++)
{
ThisGroup = (CLVDragGroup*)fDragGroups.ItemAt(GroupCounter);
if(ThisGroup->Shown)
{
fTheShownGroupAfter = ThisGroup;
fSnapGroupAfter = GroupCounter;
break;
}
}
//See if it can actually snap in the given direction
if(fSnapGroupBefore != -1)
{
if(fTheShownGroupBefore->Flags & CLV_LOCK_AT_BEGINNING)
if(!fTheDragGroup->AllLockBeginning)
fSnapGroupBefore = -1;
if(fTheDragGroup->Flags & CLV_LOCK_AT_END)
if(!fTheShownGroupBefore->AllLockEnd)
fSnapGroupBefore = -1;
}
if(fSnapGroupAfter != -1)
{
if(fTheShownGroupAfter->Flags & CLV_LOCK_AT_END)
if(!fTheDragGroup->AllLockEnd)
fSnapGroupAfter = -1;
if(fTheDragGroup->Flags & CLV_LOCK_AT_BEGINNING)
if(!fTheShownGroupAfter->AllLockBeginning)
fSnapGroupAfter = -1;
}
//Find the minumum and maximum positions for the group to snap
fSnapMin = -1.0;
fSnapMax = -1.0;
fDragBoxWidth = fTheDragGroup->GroupEnd-fTheDragGroup->GroupBegin;
if(fSnapGroupBefore != -1)
{
fSnapMin = fTheShownGroupBefore->GroupBegin + fDragBoxWidth;
if(fSnapMin > fTheShownGroupBefore->GroupEnd)
fSnapMin = fTheShownGroupBefore->GroupEnd;
}
if(fSnapGroupAfter != -1)
{
fSnapMax = fTheShownGroupAfter->GroupEnd - fDragBoxWidth;
if(fSnapMax < fTheShownGroupAfter->GroupBegin)
fSnapMax = fTheShownGroupAfter->GroupBegin;
}
}

View File

@ -1,99 +0,0 @@
//CLVColumnLabelView class header file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#ifndef _CLV_COLUMN_LABEL_VIEW_H_
#define _CLV_COLUMN_LABEL_VIEW_H_
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <View.h>
#include <List.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
//******************************************************************************************************
class ColumnListView;
class CLVColumn;
//******************************************************************************************************
//**** CLASS AND STRUCTURE DECLARATIONS, ASSOCIATED CONSTANTS AND STATIC FUNCTIONS
//******************************************************************************************************
struct CLVDragGroup
{
int32 GroupStartDispListIndex; //Indices in the column display list where this group starts
int32 GroupStopDispListIndex; //and finishes
float GroupBegin,GroupEnd; //-1.0 if whole group is hidden
CLVColumn* LastColumnShown;
bool AllLockBeginning;
bool AllLockEnd;
bool Shown; //False if none of the columns in this group are shown
uint32 Flags; //Uses CLV_NOT_MOVABLE, CLV_LOCK_AT_BEGINNING, CLV_LOCK_AT_END
};
class CLVColumnLabelView : public BView
{
public:
//Constructor and destructor
CLVColumnLabelView(BRect Bounds,ColumnListView* Parent,const BFont* Font);
~CLVColumnLabelView();
//BView overrides
virtual void Draw(BRect UpdateRect);
virtual void MouseDown(BPoint Point);
virtual void MouseMoved(BPoint where, uint32 code, const BMessage *message);
virtual void MouseUp(BPoint where);
private:
friend class ColumnListView;
friend class CLVColumn;
float fFontAscent;
BList* fDisplayList;
//Column select and drag stuff
CLVColumn* fColumnClicked;
BPoint fPreviousMousePos;
BPoint fMouseClickedPos;
bool fColumnDragging;
bool fColumnResizing;
bool fModifiedCursor;
BList fDragGroups; //Groups of CLVColumns that must drag together
int32 fDragGroup; //Index into DragGroups of the group being dragged by user
CLVDragGroup* fTheDragGroup;
CLVDragGroup* fTheShownGroupBefore;
CLVDragGroup* fTheShownGroupAfter;
int32 fSnapGroupBefore, //Index into DragGroups of TheShownGroupBefore and
fSnapGroupAfter; //TheShownGroupAfter, if the group the user is dragging is
//allowed to snap there, otherwise -1
float fDragBoxMouseHoldOffset,fResizeMouseHoldOffset;
float fDragBoxWidth; //Can include multiple columns; depends on CLV_LOCK_WITH_RIGHT
float fPrevDragOutlineLeft,fPrevDragOutlineRight;
float fSnapMin,fSnapMax; //-1.0 indicates the column can't snap in the given direction
ColumnListView* fParent;
//Private functions
void ShiftDragGroup(int32 NewPos);
void UpdateDragGroups();
void SetSnapMinMax();
};
#endif

View File

@ -1,576 +0,0 @@
//CLVListItem source file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <string.h>
#include <Region.h>
#include <ClassInfo.h>
#include <String.h>
#include <stdio.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include "CLVEasyItem.h"
#include "Colors.h"
#include "CLVColumn.h"
#include "ColumnListView.h"
#include "NewStrings.h"
//******************************************************************************************************
//**** CLVEasyItem CLASS DEFINITION
//******************************************************************************************************
CLVEasyItem::CLVEasyItem(uint32 level, bool superitem, bool expanded, float minheight)
: CLVListItem(level,superitem,expanded,minheight)
{
text_offset = 0.0;
SetTextColor(0,0,0);
fBackgroundColor=NULL;
}
CLVEasyItem::~CLVEasyItem()
{
int num_columns = m_column_types.CountItems();
for(int column = 0; column < num_columns; column++)
{
int32 type = (int32)m_column_types.ItemAt(column);
bool bitmap_is_copy = false;
if(type & CLVColFlagBitmapIsCopy)
bitmap_is_copy = true;
type &= CLVColTypesMask;
if(type == CLVColStaticText || type == CLVColTruncateText)
delete[] ((char*)m_column_content.ItemAt(column));
if(type == CLVColTruncateText)
delete[] ((char*)m_aux_content.ItemAt(column));
if(type == CLVColBitmap && bitmap_is_copy)
delete ((BBitmap*)m_column_content.ItemAt(column));
delete (BRect*)m_cached_rects.ItemAt(column);
}
SetBackgroundColor(NULL);
}
void CLVEasyItem::PrepListsForSet(int column_index)
{
int cur_num_columns = m_column_types.CountItems();
bool delete_old = (cur_num_columns >= column_index-1);
while(cur_num_columns <= column_index)
{
m_column_types.AddItem((void*)CLVColNone);
m_column_content.AddItem(NULL);
m_aux_content.AddItem(NULL);
m_cached_rects.AddItem(new BRect(-1,-1,-1,-1));
cur_num_columns++;
}
if(delete_old)
{
//Column content exists already so delete the old entries
int32 old_type = (int32)m_column_types.ItemAt(column_index);
bool bitmap_is_copy = false;
if(old_type & CLVColFlagBitmapIsCopy)
bitmap_is_copy = true;
old_type &= CLVColTypesMask;
void* old_content = m_column_content.ItemAt(column_index);
char* old_truncated = (char*)m_aux_content.ItemAt(column_index);
if(old_type == CLVColStaticText || old_type == CLVColTruncateText)
delete[] ((char*)old_content);
if(old_type == CLVColTruncateText)
delete[] old_truncated;
if(old_type == CLVColBitmap && bitmap_is_copy)
delete ((BBitmap*)old_content);
((BRect**)m_cached_rects.Items())[column_index]->Set(-1,-1,-1,-1);
}
}
void CLVEasyItem::SetColumnContent(int column_index, const char *text, bool truncate, bool right_justify)
{
PrepListsForSet(column_index);
//Create the new entry
((BRect**)m_cached_rects.Items())[column_index]->Set(-1,-1,-1,-1);
if(text == NULL || text[0] == 0)
{
((int32*)m_column_types.Items())[column_index] = CLVColNone;
((char**)m_column_content.Items())[column_index] = NULL;
((char**)m_aux_content.Items())[column_index] = NULL;
}
else
{
char* copy = Strdup_new(text);
((char**)m_column_content.Items())[column_index] = copy;
if(!truncate)
{
((int32*)m_column_types.Items())[column_index] = CLVColStaticText;
((char**)m_aux_content.Items())[column_index] = NULL;
}
else
{
((int32*)m_column_types.Items())[column_index] = CLVColTruncateText|CLVColFlagNeedsTruncation;
copy = new char[strlen(text)+3];
strcpy(copy,text);
((char**)m_aux_content.Items())[column_index] = copy;
}
if(right_justify)
((int32*)m_column_types.Items())[column_index] |= CLVColFlagRightJustify;
}
}
void CLVEasyItem::SetColumnContent(int column_index, const BBitmap *bitmap, float horizontal_offset, bool copy,
bool right_justify)
{
PrepListsForSet(column_index);
//Create the new entry
if(bitmap == NULL)
{
((int32*)m_column_types.Items())[column_index] = CLVColNone;
((char**)m_column_content.Items())[column_index] = NULL;
((char**)m_aux_content.Items())[column_index] = NULL;
}
else
{
if(copy)
((int32*)m_column_types.Items())[column_index] = CLVColBitmap|CLVColFlagBitmapIsCopy;
else
((int32*)m_column_types.Items())[column_index] = CLVColBitmap;
if(right_justify)
((int32*)m_column_types.Items())[column_index] |= CLVColFlagRightJustify;
BBitmap* the_bitmap;
if(copy)
{
the_bitmap = new BBitmap(bitmap->Bounds(),bitmap->ColorSpace());
int32 copy_ints = bitmap->BitsLength()/4;
int32* source = (int32*)bitmap->Bits();
int32* dest = (int32*)the_bitmap->Bits();
for(int32 i = 0; i < copy_ints; i++)
dest[i] = source[i];
}
else
the_bitmap = (BBitmap*)bitmap;
((BBitmap**)m_column_content.Items())[column_index] = the_bitmap;
((int32*)m_aux_content.Items())[column_index] = (int32)horizontal_offset;
}
}
void CLVEasyItem::SetColumnUserTextContent(int column_index, bool truncate, bool right_justify)
{
PrepListsForSet(column_index);
if(truncate)
((int32*)m_column_types.Items())[column_index] = CLVColTruncateUserText;
else
((int32*)m_column_types.Items())[column_index] = CLVColUserText;
if(right_justify)
((int32*)m_column_types.Items())[column_index] |= CLVColFlagRightJustify;
}
const char* CLVEasyItem::GetColumnContentText(int column_index)
{
int32 type = ((int32)m_column_types.ItemAt(column_index)) & CLVColTypesMask;
if(type == CLVColStaticText || type == CLVColTruncateText)
return (char*)m_column_content.ItemAt(column_index);
if(type == CLVColTruncateUserText || type == CLVColUserText)
return GetUserText(column_index,-1);
return NULL;
}
const BBitmap* CLVEasyItem::GetColumnContentBitmap(int column_index)
{
int32 type = ((int32)m_column_types.ItemAt(column_index)) & CLVColTypesMask;
if(type != CLVColBitmap)
return NULL;
return (BBitmap*)m_column_content.ItemAt(column_index);
}
void CLVEasyItem::DrawItemColumn(BView *owner, BRect item_column_rect, int32 column_index, bool complete)
{
rgb_color color;
bool selected = IsSelected();
if(selected)
color = ((ColumnListView*)owner)->ItemSelectColor();
else{
if(fBackgroundColor)
{
color.red = fBackgroundColor->red;
color.blue = fBackgroundColor->blue;
color.green = fBackgroundColor->green;
complete = true;
}else
color = owner->ViewColor();
}
owner->SetLowColor(color);
owner->SetDrawingMode(B_OP_COPY);
bool highlightTextOnly = ((ColumnListView*)owner)->HighlightTextOnly();
if(selected || complete)
{
owner->SetHighColor(color);
if(!highlightTextOnly && selected)
owner->FillRect(item_column_rect);
else if(!highlightTextOnly &&complete)
owner->FillRect(item_column_rect);
else if(highlightTextOnly&&complete)
owner->Invalidate(item_column_rect);
}
if(column_index == -1)
return;
int32 type = (int32)m_column_types.ItemAt(column_index);
if(type == 0)
return;
bool needs_truncation = false;
if(type & CLVColFlagNeedsTruncation)
needs_truncation = true;
bool right_justify = false;
if(type & CLVColFlagRightJustify)
right_justify = true;
type &= CLVColTypesMask;
BRegion Region;
Region.Include(item_column_rect);
owner->ConstrainClippingRegion(&Region);
BRect* cached_rect = (BRect*)m_cached_rects.ItemAt(column_index);
if(cached_rect != NULL)
*cached_rect = item_column_rect;
if(type == CLVColStaticText || type == CLVColTruncateText || type == CLVColTruncateUserText ||
type == CLVColUserText)
{
const char* text = NULL;
owner->SetDrawingMode(B_OP_COPY);
if(type == CLVColTruncateText)
{
if(needs_truncation)
{
BFont owner_font;
owner->GetFont(&owner_font);
TruncateText(column_index,item_column_rect.right-item_column_rect.left,&owner_font);
((int32*)m_column_types.Items())[column_index] &= (CLVColFlagNeedsTruncation^0xFFFFFFFF);
}
text = (const char*)m_aux_content.ItemAt(column_index);
}
else if(type == CLVColStaticText)
text = (const char*)m_column_content.ItemAt(column_index);
else if(type == CLVColTruncateUserText)
text = GetUserText(column_index,item_column_rect.right-item_column_rect.left);
else if(type == CLVColUserText)
text = GetUserText(column_index,-1);
if(text != NULL)
{
BPoint draw_point;
if(!right_justify)
draw_point.Set(item_column_rect.left+2.0,item_column_rect.top+text_offset);
else
{
BFont font;
owner->GetFont(&font);
float string_width = font.StringWidth(text);
draw_point.Set(item_column_rect.right-2.0-string_width,item_column_rect.top+text_offset);
}
if(selected && highlightTextOnly)
{
float stringWidth = owner->StringWidth(text);
if(stringWidth>0)
{
font_height FontAttributes;
BFont owner_font;
owner->GetFont(&owner_font);
owner_font.GetHeight(&FontAttributes);
float FontHeight = ceil(FontAttributes.ascent) + ceil(FontAttributes.descent);
BRect textRect(item_column_rect);
textRect.right = textRect.left + stringWidth + 3;
float pad = (textRect.Height() - FontHeight)/2.0;
textRect.top += pad;
textRect.bottom = textRect.top + FontHeight;
owner->SetHighColor(color);
owner->FillRoundRect(textRect,1,1);
}
}
owner->SetHighColor(fTextColor);
owner->DrawString(text,draw_point);
}
}
else if(type == CLVColBitmap)
{
const BBitmap* bitmap = (BBitmap*)m_column_content.ItemAt(column_index);
BRect bounds = bitmap->Bounds();
float horizontal_offset = (float)((int32)m_aux_content.ItemAt(column_index));
if(!right_justify)
{
item_column_rect.left += horizontal_offset;
item_column_rect.right = item_column_rect.left + (bounds.right-bounds.left);
}
else
{
item_column_rect.left = item_column_rect.right-horizontal_offset-(bounds.right-bounds.left);
item_column_rect.right -= horizontal_offset;
}
item_column_rect.top += ceil(((item_column_rect.bottom-item_column_rect.top)-(bounds.bottom-bounds.top))/2.0);
item_column_rect.bottom = item_column_rect.top + (bounds.bottom-bounds.top);
if(selected && highlightTextOnly)
{
BRect selectRect(item_column_rect);
owner->SetDrawingMode(B_OP_COPY);
owner->SetHighColor(color);
selectRect.bottom += 2;
selectRect.right += 3;
selectRect.top -= 2;
selectRect.left -= 1;
owner->FillRoundRect(selectRect,2,2);
}
owner->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(bitmap,item_column_rect);
owner->SetDrawingMode(B_OP_COPY);
}
owner->ConstrainClippingRegion(NULL);
}
void CLVEasyItem::Update(BView *owner, const BFont *font)
{
CLVListItem::Update(owner,font);
font_height FontAttributes;
BFont owner_font;
owner->GetFont(&owner_font);
owner_font.GetHeight(&FontAttributes);
float FontHeight = ceil(FontAttributes.ascent) + ceil(FontAttributes.descent);
text_offset = ceil(FontAttributes.ascent) + (Height()-FontHeight)/2.0;
}
int CLVEasyItem::CompareItems(const CLVListItem *a_Item1, const CLVListItem *a_Item2, int32 KeyColumn)
{
const CLVEasyItem* Item1 = cast_as(a_Item1,const CLVEasyItem);
const CLVEasyItem* Item2 = cast_as(a_Item2,const CLVEasyItem);
if(Item1 == NULL || Item2 == NULL || Item1->m_column_types.CountItems() <= KeyColumn ||
Item2->m_column_types.CountItems() <= KeyColumn)
return 0;
int32 type1 = ((int32)Item1->m_column_types.ItemAt(KeyColumn)) & CLVColTypesMask;
int32 type2 = ((int32)Item2->m_column_types.ItemAt(KeyColumn)) & CLVColTypesMask;
if(!((type1 == CLVColStaticText || type1 == CLVColTruncateText || type1 == CLVColTruncateUserText ||
type1 == CLVColUserText) && (type2 == CLVColStaticText || type2 == CLVColTruncateText ||
type2 == CLVColTruncateUserText || type2 == CLVColUserText)))
return 0;
const char* text1 = NULL;
const char* text2 = NULL;
if(type1 == CLVColStaticText || type1 == CLVColTruncateText)
text1 = (const char*)Item1->m_column_content.ItemAt(KeyColumn);
else if(type1 == CLVColTruncateUserText || type1 == CLVColUserText)
text1 = Item1->GetUserText(KeyColumn,-1);
if(type2 == CLVColStaticText || type2 == CLVColTruncateText)
text2 = (const char*)Item2->m_column_content.ItemAt(KeyColumn);
else if(type2 == CLVColTruncateUserText || type2 == CLVColUserText)
text2 = Item2->GetUserText(KeyColumn,-1);
return strcasecmp(text1,text2);
}
BRect CLVEasyItem::TruncateText(int32 column_index, float column_width, BFont* font)
{
column_width -= 4;
//Because when I draw the text I start drawing 2 pixels to the right from the column's left edge, and want
//to stop 2 pixels before the right edge
BRect invalid(-1,-1,-1,-1);
char* full_text = (char*)m_column_content.ItemAt(column_index);
char new_text[256];
char* truncated_text = (char*)m_aux_content.ItemAt(column_index);
BString STR = full_text;
font->TruncateString(&STR,B_TRUNCATE_END,column_width);
::strncpy(new_text,STR.String(),256);
//GetTruncatedString(full_text,new_text,column_width,256,font);
if(strcmp(truncated_text,new_text)!=0)
{
//The truncated text has changed
BRect* temp = (BRect*)m_cached_rects.ItemAt(column_index);
if(temp != NULL && *temp != BRect(-1,-1,-1,-1))
{
invalid = *temp;
//Figure out which region just got changed
int32 cmppos;
int32 cmplen = strlen(new_text);
char remember = 0;
for(cmppos = 0; cmppos <= cmplen; cmppos++)
if(new_text[cmppos] != truncated_text[cmppos])
{
remember = new_text[cmppos];
new_text[cmppos] = 0;
break;
}
invalid.left += 2 + font->StringWidth(new_text);
new_text[cmppos] = remember;
}
//Remember the new truncated text
strcpy(truncated_text,new_text);
}
return invalid;
}
void CLVEasyItem::ColumnWidthChanged(int32 column_index, float column_width, ColumnListView *the_view)
{
BRect* cached_rect = (BRect*)m_cached_rects.ItemAt(column_index);
if(cached_rect == NULL || *cached_rect == BRect(-1,-1,-1,-1))
return;
float width_delta = column_width-(cached_rect->right-cached_rect->left);
cached_rect->right += width_delta;
int num_columns = m_cached_rects.CountItems();
for(int column = 0; column < num_columns; column++)
if(column != column_index)
{
BRect* other_rect = (BRect*)m_cached_rects.ItemAt(column);
if(other_rect->left > cached_rect->left)
other_rect->OffsetBy(width_delta,0);
}
int32 type = (int32)m_column_types.ItemAt(column_index);
bool right_justify = (type&CLVColFlagRightJustify);
type &= CLVColTypesMask;
BRect invalid;
BFont view_font;
if(type == CLVColTruncateText)
{
BRect bounds = the_view->Bounds();
if(cached_rect->top <= bounds.bottom && cached_rect->bottom >= bounds.top)
{
//If it's onscreen, truncate and invalidate the changed area
the_view->GetFont(&view_font);
invalid = TruncateText(column_index, column_width,&view_font);
((int32*)m_column_types.Items())[column_index] &= (CLVColFlagNeedsTruncation^0xFFFFFFFF);
if(invalid != BRect(-1.0,-1.0,-1.0,-1.0))
{
if(!right_justify)
the_view->Invalidate(invalid);
else
the_view->Invalidate(*cached_rect);
}
}
else
//If it's not onscreen flag it for truncation the next time it's drawn
((int32*)m_column_types.Items())[column_index] |= CLVColFlagNeedsTruncation;
}
if(type == CLVColTruncateUserText)
{
char old_text[256];
Strtcpy(old_text,GetUserText(column_index,column_width-width_delta),256);
char new_text[256];
Strtcpy(new_text,GetUserText(column_index,column_width),256);
if(strcmp(old_text,new_text) != 0)
{
BRect* temp = (BRect*)m_cached_rects.ItemAt(column_index);
if(temp != NULL && *temp != BRect(-1,-1,-1,-1))
{
invalid = *temp;
if(!right_justify)
{
//The truncation changed, so find the point of divergence.
int change_pos = 0;
while(old_text[change_pos] == new_text[change_pos])
change_pos++;
new_text[change_pos] = 0;
the_view->GetFont(&view_font);
invalid.left += 2 + view_font.StringWidth(new_text);
the_view->Invalidate(invalid);
}
else
the_view->Invalidate(*cached_rect);
}
}
}
}
void CLVEasyItem::FrameChanged(int32 column_index, BRect new_frame, ColumnListView *the_view)
{
BRect* cached_rect = (BRect*)m_cached_rects.ItemAt(column_index);
if(cached_rect == NULL)
return;
int32 type = ((int32)m_column_types.ItemAt(column_index)) & CLVColTypesMask;
if(type == CLVColTruncateText)
if(*cached_rect != new_frame)
{
*cached_rect = new_frame;
//If it's onscreen, truncate and invalidate the changed area
if(new_frame.Intersects(the_view->Bounds()))
{
BFont view_font;
the_view->GetFont(&view_font);
BRect invalid = TruncateText(column_index, new_frame.right-new_frame.left,&view_font);
((int32*)m_column_types.Items())[column_index] &= (CLVColFlagNeedsTruncation^0xFFFFFFFF);
if(invalid != BRect(-1.0,-1.0,-1.0,-1.0))
the_view->Invalidate(invalid);
}
else
//If it's not onscreen flag it for truncation the next time it's drawn
((int32*)m_column_types.Items())[column_index] |= CLVColFlagNeedsTruncation;
}
}
const char* CLVEasyItem::GetUserText(int32 column_index, float column_width) const
{
return NULL;
}
void CLVEasyItem::SetTextColor(uchar red,uchar green,uchar blue)
{
fTextColor.red = red;
fTextColor.green = green;
fTextColor.blue = blue;
}
void CLVEasyItem::SetBackgroundColor(rgb_color *color)
{
delete fBackgroundColor;
if(color)
{
fBackgroundColor = new rgb_color;
fBackgroundColor->red = color->red;
fBackgroundColor->blue = color->blue;
fBackgroundColor->green = color->green;
}else
fBackgroundColor = NULL;
}

View File

@ -1,98 +0,0 @@
//CLVEasyItem header file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#ifndef _CLV_EASY_ITEM_H_
#define _CLV_EASY_ITEM_H_
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <List.h>
#include <GraphicsDefs.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
//******************************************************************************************************
#include "CLVListItem.h"
//******************************************************************************************************
//**** TYPE DEFINITIONS AND CONSTANTS
//******************************************************************************************************
enum
{
CLVColNone = 0x00000000,
CLVColStaticText = 0x00000001,
CLVColTruncateText = 0x00000002,
CLVColBitmap = 0x00000003,
CLVColUserText = 0x00000004,
CLVColTruncateUserText = 0x00000005,
CLVColTypesMask = 0x00000007,
CLVColFlagBitmapIsCopy = 0x00000008,
CLVColFlagNeedsTruncation = 0x00000010,
CLVColFlagRightJustify = 0x00000020
};
//******************************************************************************************************
//**** CLVEasyItem CLASS DECLARATION
//******************************************************************************************************
class CLVEasyItem : public CLVListItem
{
public:
//Constructor and destructor
CLVEasyItem(uint32 level = 0, bool superitem = false, bool expanded = false, float minheight = 0.0);
virtual ~CLVEasyItem();
virtual void SetColumnContent(int column_index, const BBitmap *bitmap, float horizontal_offset = 2.0,
bool copy = true, bool right_justify = false);
virtual void SetColumnContent(int column_index, const char *text, bool truncate = true,
bool right_justify = false);
virtual void SetColumnUserTextContent(int column_index, bool truncate = true, bool right_justify = false);
const char* GetColumnContentText(int column_index);
const BBitmap* GetColumnContentBitmap(int column_index);
virtual void DrawItemColumn(BView* owner, BRect item_column_rect, int32 column_index, bool complete);
virtual void Update(BView *owner, const BFont *font);
static int CompareItems(const CLVListItem* a_Item1, const CLVListItem* a_Item2, int32 KeyColumn);
BRect TruncateText(int32 column_index, float column_width, BFont* font);
//Returns the area that needs to be redrawn, or BRect(-1,-1,-1,-1) if nothing
virtual void ColumnWidthChanged(int32 column_index, float column_width, ColumnListView* the_view);
virtual void FrameChanged(int32 column_index, BRect new_frame, ColumnListView* the_view);
inline float GetTextOffset() {return text_offset;}
virtual const char* GetUserText(int32 column_index, float column_width) const;
void SetTextColor(uchar red,uchar green,uchar blue);
void SetBackgroundColor(rgb_color *color);
BList m_column_types; //List of int32's converted from CLVColumnTypes
BList m_column_content; //List of char* (full content) or BBitmap*
private:
void PrepListsForSet(int column_index);
BList m_aux_content; //List of char* (truncated content) or int32 for bitmap horizontal offset
BList m_cached_rects; //List of BRect for truncated text
protected:
float text_offset;
rgb_color fTextColor;
rgb_color *fBackgroundColor;
};
#endif

View File

@ -1,231 +0,0 @@
//CLVListItem source file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include <Region.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include "CLVListItem.h"
#include "ColumnListView.h"
#include "CLVColumn.h"
//******************************************************************************************************
//**** CLVItem CLASS DEFINITION
//******************************************************************************************************
CLVListItem::CLVListItem(uint32 level, bool superitem, bool expanded, float minheight)
: BListItem(level, expanded),
fExpanderButtonRect(-1.0,-1.0,-1.0,-1.0),
fExpanderColumnRect(-1.0,-1.0,-1.0,-1.0)
{
fSuperItem = superitem;
fOutlineLevel = level;
fMinHeight = minheight;
}
CLVListItem::~CLVListItem()
{ }
BRect CLVListItem::ItemColumnFrame(int32 column_index, ColumnListView* owner)
{
BList* ColumnList = &owner->fColumnList;
CLVColumn* ThisColumn = (CLVColumn*)ColumnList->ItemAt(column_index);
if(!ThisColumn->IsShown())
return BRect(-1,-1,-1,-1);
int32 DisplayIndex = owner->IndexOf(this);
BRect itemRect;
if(DisplayIndex >= 0)
itemRect = owner->ItemFrame(DisplayIndex);
else
return BRect(-1,-1,-1,-1);
//Figure out what the limit is for expanders pushing other columns
float PushMax = 100000;
if(ThisColumn->fPushedByExpander || (ThisColumn->fFlags & CLV_EXPANDER))
{
BList* DisplayList = &owner->fColumnDisplayList;
int32 NumberOfColumns = DisplayList->CountItems();
for(int32 Counter = 0; Counter < NumberOfColumns; Counter++)
{
CLVColumn* SomeColumn = (CLVColumn*)DisplayList->ItemAt(Counter);
if((SomeColumn->fFlags & CLV_EXPANDER) || SomeColumn->fPushedByExpander)
PushMax = SomeColumn->fColumnEnd;
}
}
BRect ThisColumnRect = itemRect;
ThisColumnRect.left = ThisColumn->fColumnBegin;
ThisColumnRect.right = ThisColumn->fColumnEnd;
if(ThisColumn->fFlags & CLV_EXPANDER)
{
ThisColumnRect.right += OutlineLevel() * 20.0;
if(ThisColumnRect.right > PushMax)
ThisColumnRect.right = PushMax;
}
else
{
if(ThisColumn->fPushedByExpander)
{
float Shift = OutlineLevel() * 20.0;
ThisColumnRect.left += Shift;
ThisColumnRect.right += Shift;
if(Shift > 0.0 && ThisColumnRect.right > PushMax)
ThisColumnRect.right = PushMax;
}
}
if(ThisColumnRect.right >= ThisColumnRect.left)
return ThisColumnRect;
else
return BRect(-1,-1,-1,-1);
}
void CLVListItem::DrawItem(BView* owner, BRect itemRect, bool complete)
{
BList* DisplayList = &((ColumnListView*)owner)->fColumnDisplayList;
int32 NumberOfColumns = DisplayList->CountItems();
float PushMax = itemRect.right;
CLVColumn* ThisColumn;
BRect ThisColumnRect = itemRect;
float ExpanderDelta = OutlineLevel() * 20.0;
//Figure out what the limit is for expanders pushing other columns
for(int32 Counter = 0; Counter < NumberOfColumns; Counter++)
{
ThisColumn = (CLVColumn*)DisplayList->ItemAt(Counter);
if((ThisColumn->fFlags & CLV_EXPANDER) || ThisColumn->fPushedByExpander)
PushMax = ThisColumn->fColumnEnd;
}
BRegion ClippingRegion;
if(!complete)
owner->GetClippingRegion(&ClippingRegion);
else
ClippingRegion.Set(itemRect);
float LastColumnEnd = -1.0;
//Draw the columns
for(int32 Counter = 0; Counter < NumberOfColumns; Counter++)
{
ThisColumn = (CLVColumn*)DisplayList->ItemAt(Counter);
if(!ThisColumn->IsShown())
continue;
ThisColumnRect.left = ThisColumn->fColumnBegin;
ThisColumnRect.right = LastColumnEnd = ThisColumn->fColumnEnd;
float Shift = 0.0;
if((ThisColumn->fFlags & CLV_EXPANDER) || ThisColumn->fPushedByExpander)
Shift = ExpanderDelta;
if(ThisColumn->fFlags & CLV_EXPANDER)
{
ThisColumnRect.right += Shift;
if(ThisColumnRect.right > PushMax)
ThisColumnRect.right = PushMax;
fExpanderColumnRect = ThisColumnRect;
if(ClippingRegion.Intersects(ThisColumnRect))
{
//Give the programmer a chance to do his kind of highlighting if the item is selected
DrawItemColumn(owner, ThisColumnRect,
((ColumnListView*)owner)->fColumnList.IndexOf(ThisColumn),complete);
if(fSuperItem)
{
//Draw the expander, clip manually
float TopOffset = ceil((ThisColumnRect.bottom-ThisColumnRect.top-10.0)/2.0);
float LeftOffset = ThisColumn->fColumnEnd + Shift - 3.0 - 10.0;
float RightClip = LeftOffset + 10.0 - ThisColumnRect.right;
if(RightClip < 0.0)
RightClip = 0.0;
BBitmap* Arrow;
if(IsExpanded())
Arrow = &((ColumnListView*)owner)->fDownArrow;
else
Arrow = &((ColumnListView*)owner)->fRightArrow;
if(LeftOffset <= ThisColumnRect.right)
{
fExpanderButtonRect.Set(LeftOffset,ThisColumnRect.top+TopOffset,
LeftOffset+10.0-RightClip,ThisColumnRect.top+TopOffset+10.0);
owner->SetDrawingMode(B_OP_OVER);
owner->DrawBitmap(Arrow, BRect(0.0,0.0,10.0-RightClip,10.0),fExpanderButtonRect);
owner->SetDrawingMode(B_OP_COPY);
}
else
fExpanderButtonRect.Set(-1.0,-1.0,-1.0,-1.0);
}
}
}
else
{
ThisColumnRect.left += Shift;
ThisColumnRect.right += Shift;
if(Shift > 0.0 && ThisColumnRect.right > PushMax)
ThisColumnRect.right = PushMax;
if(ThisColumnRect.right >= ThisColumnRect.left && ClippingRegion.Intersects(ThisColumnRect))
DrawItemColumn(owner, ThisColumnRect,
((ColumnListView*)owner)->fColumnList.IndexOf(ThisColumn),complete);
}
}
//Fill the area after all the columns (so the select highlight goes all the way across)
ThisColumnRect.left = LastColumnEnd + 1.0;
ThisColumnRect.right = owner->Bounds().right;
if(ThisColumnRect.left <= ThisColumnRect.right && ClippingRegion.Intersects(ThisColumnRect))
DrawItemColumn(owner, ThisColumnRect,-1,complete);
}
float CLVListItem::ExpanderShift(int32 column_index, ColumnListView* owner)
{
CLVColumn* ThisColumn = owner->ColumnAt(column_index);
if(!(ThisColumn->fPushedByExpander || ThisColumn->fFlags & CLV_EXPANDER))
return 0.0;
else
return OutlineLevel() * 20.0;
}
void CLVListItem::Update(BView* owner, const BFont* font)
{
BListItem::Update(owner,font);
float ItemHeight = Height();
if(ItemHeight < fMinHeight)
ItemHeight = fMinHeight;
SetHeight(ItemHeight);
}
void CLVListItem::ColumnWidthChanged(int32 column_index, float column_width, ColumnListView* the_view)
{
//Get rid of a warning
column_index = 0;
column_width = 0;
the_view = NULL;
}
void CLVListItem::FrameChanged(int32 column_index, BRect new_frame, ColumnListView* the_view)
{
//Get rid of a warning
column_index = 0;
new_frame.left = 0;
the_view = NULL;
}

View File

@ -1,82 +0,0 @@
//CLVListItem header file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#ifndef _CLV_LIST_ITEM_H_
#define _CLV_LIST_ITEM_H_
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <ListItem.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
//******************************************************************************************************
class ColumnListView;
//******************************************************************************************************
//**** CLVListItem CLASS DECLARATION
//******************************************************************************************************
class CLVListItem : public BListItem
{
public:
//Constructor and destructor
CLVListItem(uint32 level = 0, bool superitem = false, bool expanded = false, float minheight = 0.0);
virtual ~CLVListItem();
//Archival stuff
/* Not implemented yet
CLVItem(BMessage* archive);
static CLVItem* Instantiate(BMessage* data);
virtual status_t Archive(BMessage* data, bool deep = true) const;
*/
virtual void DrawItemColumn(BView* owner, BRect item_column_rect, int32 column_index,
bool complete) = 0; //column_index (0-N) is based on the order in which the columns were added
//to the ColumnListView, not the display order. An index of -1 indicates
//that the program needs to draw a blank area beyond the last column. The
//main purpose is to allow the highlighting bar to continue all the way to
//the end of the ColumnListView, even after the end of the last column.
virtual void DrawItem(BView* owner, BRect itemRect, bool complete);
//In general, you don't need or want to override DrawItem().
BRect ItemColumnFrame(int32 column_index, ColumnListView* owner);
float ExpanderShift(int32 column_index, ColumnListView* owner);
virtual void Update(BView* owner, const BFont* font);
inline bool IsSuperItem() const {return fSuperItem;}
inline void SetSuperItem(bool superitem) {fSuperItem = superitem;}
inline uint32 OutlineLevel() const {return fOutlineLevel;}
inline void SetOutlineLevel(uint32 level) {fOutlineLevel = level;}
inline bool ExpanderRectContains(BPoint where) {return fExpanderButtonRect.Contains(where);}
virtual void ColumnWidthChanged(int32 column_index, float column_width, ColumnListView* the_view);
virtual void FrameChanged(int32 column_index, BRect new_frame, ColumnListView* the_view);
private:
friend class ColumnListView;
bool fSuperItem;
uint32 fOutlineLevel;
float fMinHeight;
BRect fExpanderButtonRect;
BRect fExpanderColumnRect;
BList* fSortingContextBList;
ColumnListView* fSortingContextCLV;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,238 +0,0 @@
//Column list view header file
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#ifndef _CLV_COLUMN_LIST_VIEW_H_
#define _CLV_COLUMN_LIST_VIEW_H_
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <ListView.h>
//******************************************************************************************************
//**** PROJECT HEADER FILES AND CLASS NAME DECLARATIONS
//******************************************************************************************************
#include "Colors.h"
#include "CLVColumn.h"
class CLVListItem;
class CLVColumnLabelView;
class CLVFillerView;
class CLVContainerView;
#include "PrefilledBitmap.h"
#include "BetterScrollView.h"
//******************************************************************************************************
//**** CONSTANTS AND TYPE DEFINITIONS
//******************************************************************************************************
typedef int (*CLVCompareFuncPtr)(const CLVListItem* item1, const CLVListItem* item2, int32 sort_key);
//******************************************************************************************************
//**** ColumnListView CLASS DECLARATION
//******************************************************************************************************
class ColumnListView : public BListView
{
public:
//Constructor and destructor
ColumnListView( BRect Frame,
CLVContainerView** ContainerView, //Used to get back a pointer to the container
//view that will hold the ColumnListView, the
//the CLVColumnLabelView, and the scrollbars.
//If no scroll bars or border are asked for,
//this will act like a plain BView container.
const char* Name = NULL,
uint32 ResizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE,
list_view_type Type = B_SINGLE_SELECTION_LIST,
bool hierarchical = false,
bool horizontal = true, //Which scroll bars should I add, if any
bool vertical = true,
bool scroll_view_corner = true,
border_style border = B_NO_BORDER, //What type of border to add, if any
const BFont* LabelFont = be_plain_font);
virtual ~ColumnListView();
//Archival stuff
/*** Not implemented yet
ColumnListView(BMessage* archive);
static ColumnListView* Instantiate(BMessage* data);
virtual status_t Archive(BMessage* data, bool deep = true) const;
***/
//Column setup functions
virtual bool AddColumn(CLVColumn* Column); //Note that a column may only be added to
//one ColumnListView at a time, and may not
//be added more than once to the same
//ColumnListView without removing it
//inbetween
virtual bool AddColumnList(BList* NewColumns);
virtual bool RemoveColumn(CLVColumn* Column);
virtual bool RemoveColumns(CLVColumn* Column, int32 Count); //Finds Column in ColumnList
//and removes Count columns and
//their data from the view
//and its items
int32 CountColumns() const;
int32 IndexOfColumn(CLVColumn* column) const;
CLVColumn* ColumnAt(int32 column_index) const;
virtual bool SetDisplayOrder(const int32* Order);
//Sets the display order: each int32 in the Order list specifies the column index of the
//next column to display. Note that this DOES NOT get called if the user drags a
//column, so overriding it will not inform you of user changes. If you need that info,
//override DisplayOrderChanged instead. Also note that SetDisplayOrder does call
//DisplayOrderChanged(false).
void GetDisplayOrder(int32* order) const;
//Fills a caller-provided array with the display order of the columns in the same format
//as used in calling SetDisplayOrder. The order pointer should point to an array
//int32 order[n] where n is the number of columns in the ColumnListView.
virtual void ColumnWidthChanged(int32 ColumnIndex, float NewWidth);
virtual void DisplayOrderChanged(const int32* order);
//Override this if you want to find out when the display order changed.
virtual void SetSortKey(int32 ColumnIndex, bool doSort = true);
//Set it to -1 to remove the sort key.
virtual void AddSortKey(int32 ColumnIndex, bool doSort = true);
void ReverseSortMode(int32 ColumnIndex, bool doSort = true);
virtual void SetSortMode(int32 ColumnIndex,CLVSortMode Mode, bool doSort = true);
//Override this to filter the modes
int32 GetSorting(int32* SortKeys, CLVSortMode* SortModes) const;
//Returns the number of used sort keys, and fills the provided arrays with the sort keys
//by column index and sort modes, in priority order. The pointers should point to an array
//int32 SortKeys[n], and an array CLVSortMode SortModes[n] where n is the number of sortable
//columns in the ColumnListView. Note: sorting will only occur if the key column is shown.
void SetSorting(int32 NumberOfKeys, int32* SortKeys, CLVSortMode* SortModes, bool doSort = true);
//Sets the sorting parameters using the same format returned by Sorting
virtual void SortingChanged(); //Override this to detect changes to the sorting keys or modes.
inline void SetItemSelectColor(bool window_active, rgb_color color)
{
if(window_active) fSelectedItemColorWindowActive = color;
else fSelectedItemColorWindowInactive = color;
}
inline rgb_color ItemSelectColor(bool window_active) const
{
if(window_active) return fSelectedItemColorWindowActive;
return fSelectedItemColorWindowInactive;
}
inline rgb_color ItemSelectColor() const
{
if(fWindowActive) return fSelectedItemColorWindowActive;
return fSelectedItemColorWindowInactive;
}
//BView overrides
virtual void FrameResized(float Width, float Height);
virtual void ScrollTo(BPoint point);
virtual void MouseDown(BPoint point);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 code, const BMessage* message);
virtual void WindowActivated(bool active);
//List functions
virtual bool AddUnder(BListItem* item, BListItem* superitem);
virtual bool AddItem(BListItem* item, int32 fullListIndex);
virtual bool AddItem(BListItem* item);
virtual bool AddList(BList* newItems); //This must be a BList of
//BListItem*'s, NOT CLVListItem*'s
virtual bool AddList(BList* newItems, int32 fullListIndex); //This must be a BList of
//BListItem*'s, NOT CLVListItem*'s
virtual bool EfficientAddListHierarchical(BList* newItems, int32 fullListIndex, bool expanded);
//visible indicates whether or not the items are under an item which is expanded. If
//expanded is false, NONE of these items will be showing. If expanded is true, ALL of
//them will be, so make sure that all of them are in an expanded state. Not checking is
//done for you. The list is of BListItem*'s, NOT CLVListItem*'s.
virtual bool RemoveItem(BListItem* item);
virtual BListItem* RemoveItem(int32 fullListIndex); //Actually returns CLVListItem
virtual bool RemoveItems(int32 fullListIndex, int32 count);
virtual void MakeEmpty();
CLVListItem* FullListItemAt(int32 fullListIndex) const;
int32 FullListIndexOf(const CLVListItem* item) const;
int32 FullListIndexOf(BPoint point) const;
CLVListItem* FullListFirstItem() const;
CLVListItem* FullListLastItem() const;
bool FullListHasItem(const CLVListItem* item) const;
int32 FullListCountItems() const;
bool FullListIsEmpty() const;
int32 FullListCurrentSelection(int32 index = 0) const;
void FullListDoForEach(bool (*func)(CLVListItem*));
void FullListDoForEach(bool (*func)(CLVListItem*, void*), void* arg2);
CLVListItem* Superitem(const CLVListItem* item) const;
int32 FullListNumberOfSubitems(const CLVListItem* item) const;
virtual void Expand(CLVListItem* item);
virtual void Collapse(CLVListItem* item);
bool IsExpanded(int32 fullListIndex) const;
void SetSortFunction(CLVCompareFuncPtr compare);
void SortItems();
virtual CLVContainerView* CreateContainer(bool horizontal, bool vertical, bool scroll_view_corner,
border_style border, uint32 ResizingMode, uint32 flags);
bool HighlightTextOnly() {return fHighlightTextOnly;}
void SetHighlightTextOnly(bool enable) {fHighlightTextOnly = enable;}
private:
friend class CLVMainView;
friend class CLVColumn;
friend class CLVColumnLabelView;
friend class CLVListItem;
void UpdateColumnSizesDataRectSizeScrollBars(bool scrolling_allowed = true);
void ColumnsChanged();
void EmbedInContainer(bool horizontal, bool vertical, bool scroll_view_corner, border_style border,
uint32 ResizingMode, uint32 flags);
void SortListArray(CLVListItem** SortArray, int32 NumberOfItems);
void MakeEmptyPrivate();
bool AddHierarchicalListPrivate(BList* newItems, int32 fullListIndex);
bool AddItemPrivate(CLVListItem* item, int32 fullListIndex);
void SortFullListSegment(int32 OriginalListStartIndex, int32 InsertionPoint, BList* NewList);
BList* SortItemsInThisLevel(int32 OriginalListStartIndex);
static int PlainBListSortFunc(BListItem** item1, BListItem** item2);
static int HierarchicalBListSortFunc(BListItem** item1, BListItem** item2);
CLVColumnLabelView* fColumnLabelView;
CLVContainerView* fScrollView;
bool fHierarchical;
BList fColumnList;
BList fColumnDisplayList;
BList fSortKeyList; //List contains CLVColumn pointers
BList fFullItemList; //List contains CLVListItem pointers
PrefilledBitmap fRightArrow;
PrefilledBitmap fDownArrow;
int32 fExpanderColumn;
CLVCompareFuncPtr fCompare;
bool fWatchingForDrag;
BPoint fLastMouseDown;
int32 fNoKeyMouseDownItemIndex;
rgb_color fSelectedItemColorWindowActive;
rgb_color fSelectedItemColorWindowInactive;
bool fWindowActive;
bool fHighlightTextOnly;
};
class CLVContainerView : public BetterScrollView
{
public:
CLVContainerView(ColumnListView* target, uint32 resizingMode, uint32 flags, bool horizontal, bool vertical,
bool scroll_view_corner, border_style border);
~CLVContainerView();
private:
friend class ColumnListView;
bool IsBeingDestroyed;
};
#endif

View File

@ -1,166 +0,0 @@
//******************************************************************************************************
//**** PROJECT HEADER FILES
//******************************************************************************************************
#include "Cursors.h"
//******************************************************************************************************
//**** CONSTANT DEFINITIONS
//******************************************************************************************************
uint8 c_v_resize_cursor_data[68] =
{
16,1,7,7,
0,0, //0000000000000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
17,16, //0001000100010000
49,24, //0011000100011000
113,28, //0111000100011100
49,24, //0011000100011000
17,16, //0001000100010000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
0,0, //0000000000000000
0,0, //0000000000000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
27,176, //0001101110110000
59,184, //0011101110111000
123,188,//0111101110111100
251,190,//1111101110111110
123,188,//0111101110111100
59,184, //0011101110111000
27,176, //0001101110110000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
0,0 //0000000000000000
};
uint8 c_h_resize_cursor_data[68] =
{
16,1,7,7,
0,0, //0000000000000000
1,0, //0000000100000000
3,128, //0000001110000000
7,192, //0000011111000000
0,0, //0000000000000000
0,0, //0000000000000000
0,0, //0000000000000000
127,252,//0111111111111100
0,0, //0000000000000000
0,0, //0000000000000000
0,0, //0000000000000000
7,192, //0000011111000000
3,128, //0000001110000000
1,0, //0000000100000000
0,0, //0000000000000000
0,0, //0000000000000000
1,0, //0000000100000000
3,128, //0000001110000000
7,192, //0000011111000000
15,224, //0000111111100000
15,224, //0000111111100000
0,0, //0000000000000000
255,254,//1111111111111110
255,254,//1111111111111110
255,254,//1111111111111110
0,0, //0000000000000000
15,224, //0000111111100000
15,224, //0000111111100000
7,192, //0000011111000000
3,128, //0000001110000000
1,0, //0000000100000000
0,0 //0000000000000000
};
uint8 c_crosshairs_cursor_data[68] =
{
16,1,7,7,
0,0, //0000000000000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
0,0, //0000000000000000
125,124,//0111110101111100
0,0, //0000000000000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
1,0, //0000000100000000
0,0, //0000000000000000
0,0, //0000000000000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
255,254,//1111111111111110
255,254,//1111111111111110
255,254,//1111111111111110
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
3,128, //0000001110000000
0,0 //0000000000000000
};
uint8 c_magnify_cursor_data[68] =
{
16,1,6,6,
0,0, //0000000000000000
7,0, //0000011100000000
24,192, //0001100011000000
32,32, //0010000000100000
32,32, //0010000000100000
64,16, //0100000000010000
64,16, //0100000000010000
64,16, //0100000000010000
32,32, //0010000000100000
32,32, //0010000000100000
24,240, //0001100011110000
7,56, //0000011100111000
0,28, //0000000000011100
0,14, //0000000000001110
0,4, //0000000000000100
0,0, //0000000000000000
7,0, //0000011100000000
31,192, //0001111111000000
63,224, //0011111111100000
120,240,//0111100011110000
112,112,//0111000001110000
224,56, //1110000000111000
224,56, //1110000000111000
224,56, //1110000000111000
112,112,//0111000001110000
120,240,//0111100011110000
63,248, //0011111111111000
31,252, //0001111111111100
7,62, //0000011100111110
0,31, //0000000000011111
0,14, //0000000000001110
0,4, //0000000000000100
};
const void* c_v_resize_cursor = c_v_resize_cursor_data;
const void* c_h_resize_cursor = c_h_resize_cursor_data;
const void* c_crosshairs_cursor = c_crosshairs_cursor_data;
const void* c_magnify_cursor = c_magnify_cursor_data;

View File

@ -1,20 +0,0 @@
#ifndef _SGB_CURSORS_H_
#define _SGB_CURSORS_H_
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <SupportDefs.h>
//******************************************************************************************************
//**** CONSTANT DEFINITIONS
//******************************************************************************************************
extern const void* c_v_resize_cursor;
extern const void* c_h_resize_cursor;
extern const void* c_crosshairs_cursor;
extern const void* c_magnify_cursor;
#endif //_SGB_CURSORS_H_

View File

@ -1,19 +0,0 @@
const unsigned char kDescendingIconBits [] = {
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};

View File

@ -1,244 +0,0 @@
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#include <string.h>
#include <Font.h>
#include <Looper.h>
#include <Rect.h>
#include "NewStrings.h"
float GetStringsMaxWidth(const char** strings, int32 num_strings, const BFont* font,
float* string_widths)
//Fills the stringsWidths array with the width of each individual string in the array using
//BFont::GetStringWidths(), then finds the longest string width in the array and returns that width.
//If a string_widths array is provided, it fills it in with the length of each string.
{
int32 strlens_fixed[20];
int32* strlens;
bool release_string_lengths = false;
if(num_strings <= 20)
strlens = strlens_fixed;
else
{
strlens = new int32[num_strings];
release_string_lengths = true;
}
float strwidths_fixed[20];
bool release_string_widths = false;
if(string_widths == NULL)
{
if(num_strings <= 20)
string_widths = strwidths_fixed;
else
{
string_widths = new float[num_strings];
release_string_widths = true;
}
}
int32 i;
for(i = 0; i < num_strings; i++)
strlens[i] = strlen(strings[i]);
font->GetStringWidths(strings,strlens,num_strings,string_widths);
float max = string_widths[0];
for(i = 1; i < num_strings; i++)
if(string_widths[i] > max)
max = string_widths[i];
if(release_string_widths)
delete[] string_widths;
if(release_string_lengths)
delete[] strlens;
return max;
}
BRect StringBoundingBox(const char* string, const BFont* font, bool full_height, bool round_up)
{
const char* string_array[1] = {string};
struct escapement_delta delta_array[1] = {{0,0}};
BRect rect_array[1];
font->GetBoundingBoxesForStrings(string_array,1,B_SCREEN_METRIC,delta_array,rect_array);
if(full_height)
{
struct font_height font_height_struct;
font->GetHeight(&font_height_struct);
rect_array[0].top = 0-font_height_struct.ascent;
rect_array[0].bottom = font_height_struct.descent;
}
if(round_up)
{
rect_array[0].left = floor(rect_array[0].left);
rect_array[0].top = floor(rect_array[0].top);
rect_array[0].right = ceil(rect_array[0].right);
rect_array[0].bottom = ceil(rect_array[0].bottom);
}
return rect_array[0];
}
BRect GetMaxStringBoundingBoxes(const char** strings, int32 num_strings, const BFont* font,
BRect* rects, bool full_height, bool round_up)
{
BRect rects_fixed[20];
bool release_rects = false;
if(rects == NULL)
{
if(num_strings <= 20)
rects = rects_fixed;
else
{
rects = new BRect[num_strings];
release_rects = true;
}
}
struct escapement_delta delta_array_fixed[20];
bool release_deltas = false;
struct escapement_delta* delta_array = delta_array_fixed;
if(num_strings > 20)
{
delta_array = new escapement_delta[num_strings];
release_deltas = true;
}
int32 i;
for(i=0; i<num_strings; i++)
{
delta_array[i].nonspace = 0;
delta_array[i].space = 0;
}
font->GetBoundingBoxesForStrings(strings,num_strings,B_SCREEN_METRIC,delta_array,rects);
struct font_height font_height_struct;
if(full_height)
{
font->GetHeight(&font_height_struct);
if(round_up)
{
font_height_struct.ascent = ceil(font_height_struct.ascent);
font_height_struct.descent = ceil(font_height_struct.descent);
}
for(i=0; i<num_strings; i++)
{
rects[i].top = 0-font_height_struct.ascent;
rects[i].bottom = font_height_struct.descent;
}
}
if(round_up)
for(i=0; i<num_strings; i++)
{
rects[i].left = floor(rects[i].left);
rects[i].right = ceil(rects[i].right);
if(!full_height)
{
rects[i].top = floor(rects[i].top);
rects[i].bottom = ceil(rects[i].bottom);
}
}
BRect max = rects[0];
for(i=0; i<num_strings; i++)
{
if(max.left > rects[i].left)
max.left = rects[i].left;
if((!full_height) && max.top > rects[i].top)
max.top = rects[i].top;
if(max.right < rects[i].right)
max.right = rects[i].right;
if((!full_height) && max.bottom < rects[i].bottom)
max.bottom = rects[i].bottom;
}
if(release_rects)
delete[] rects;
if(release_deltas)
delete[] delta_array;
return max;
}
char* Strdup_new(const char* source)
{
char* dest = new char[strlen(source)+1];
strcpy(dest,source);
return dest;
}
char* Strcat_new(const char* string_1, const char* string_2)
{
int len_1 = strlen(string_1);
char* dest = new char[len_1+strlen(string_2)+1];
strcpy(dest,string_1);
strcpy(&dest[len_1],string_2);
return dest;
}
char* Strcat_new(const char* string_1, const char* string_2, const char* string_3)
{
int len_1 = strlen(string_1);
int len_2 = strlen(string_2);
char* dest = new char[len_1+len_2+strlen(string_3)+1];
strcpy(dest,string_1);
strcpy(&dest[len_1],string_2);
strcpy(&dest[len_1+len_2],string_3);
return dest;
}
char* Strcat_new(const char* string_1, const char* string_2, const char* string_3, const char* string_4)
{
int len_1 = strlen(string_1);
int len_2 = strlen(string_2);
int len_3 = strlen(string_3);
char* dest = new char[len_1+len_2+len_3+strlen(string_4)+1];
strcpy(dest,string_1);
strcpy(&dest[len_1],string_2);
strcpy(&dest[len_1+len_2],string_3);
strcpy(&dest[len_1+len_2+len_3],string_4);
return dest;
}
char *Strtcpy(char *dst, const char *src, int len)
{
strncpy(dst,src,len-1);
dst[len-1] = 0;
return dst;
}
void StrToUpper(char* string)
{
while(*string != 0)
{
if(*string >= 'a' && *string <= 'z')
*string = *string - 'a' + 'A';
string++;
}
}
void StrToLower(char* string)
{
while(*string != 0)
{
if(*string >= 'A' && *string <= 'Z')
*string = *string - 'A' + 'a';
string++;
}
}

View File

@ -1,48 +0,0 @@
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#ifndef _SGB_NEW_STRINGS_H_
#define _SGB_NEW_STRINGS_H_
#include <SupportDefs.h>
//Fills the StringsWidths array with the width of each individual string in the array using
//BFont::GetStringWidths(), then finds the longest string width in the array and returns that width.
//If a string_widths array is provided, it fills it in with the length of each string.
float GetStringsMaxWidth(const char** strings, int32 num_strings, const BFont* font,
float* string_widths = NULL);
//Gets the bounding box for one or more strings. If full_height is true, it increases the top and bottom to
//the font's ascent and descent. If round_up is true, it rounds each edge up to the next pixel to get the
//box that will actually be occupied onscreen.
BRect StringBoundingBox(const char* string, const BFont* font, bool full_height = false,
bool round_up = true);
BRect GetMaxStringBoundingBoxes(const char** strings, int32 num_strings, const BFont* font,
BRect* rects = NULL, bool full_height = false, bool round_up = true);
//Each of these functions either duplicates or concatenates the strings into a new char array allocated
//with new. The resulting char array must be delete[]'d when finished with it.
char *Strdup_new(const char *source);
char *Strcat_new(const char *string_1, const char *string_2);
char *Strcat_new(const char *string_1, const char *string_2, const char *string_3);
char *Strcat_new(const char *string_1, const char *string_2, const char *string_3, const char *string_4);
//Added because due to some error, the Be libraries on x86 don't export strtcopy. Len includes the null
//terminator.
char *Strtcpy(char *dst, const char *src, int len);
//Just some handy functions....
void StrToUpper(char* string);
void StrToLower(char* string);
#endif

View File

@ -1,32 +0,0 @@
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#include "PrefilledBitmap.h"
PrefilledBitmap::PrefilledBitmap(BRect bounds, color_space space, const void *data, int32 length,
bool acceptsViews, bool needsContiguousMemory)
: BBitmap(bounds, space, acceptsViews, needsContiguousMemory)
{
if(length == 0)
{
if(space == B_CMAP8)
length = ((int32(bounds.right-bounds.left+1)+3)&0xFFFFFFFC)*int32(bounds.bottom-bounds.top+1);
else if(space == B_RGB32)
length = int32(bounds.right-bounds.left+1)*int32(bounds.bottom-bounds.top+1)*3;
}
SetBits(data, length, 0, space);
}
PrefilledBitmap::~PrefilledBitmap()
{ }

View File

@ -1,42 +0,0 @@
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
//*** DESCRIPTION ***
//Useful until be implements BBitmap::BBitmap(BRect bounds, color_space space, const void *data,
// bool acceptsViews, bool needsContiguousMemory)
//or something like it...
#ifndef _SGB_PREFILLED_BITMAP_H_
#define _SGB_PREFILLED_BITMAP_H_
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <Bitmap.h>
//******************************************************************************************************
//**** CLASS DECLARATIONS
//******************************************************************************************************
class PrefilledBitmap : public BBitmap
{
public:
PrefilledBitmap(BRect bounds, color_space space, const void *data, int32 length = 0,
bool acceptsViews = false, bool needsContiguousMemory = false);
//length can be automatically calculated for B_CMAP8 and B_RGB32
~PrefilledBitmap();
};
#endif

View File

@ -1,41 +0,0 @@
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
#include <ScrollBar.h>
#include "Colors.h"
#include "ScrollViewCorner.h"
ScrollViewCorner::ScrollViewCorner(float Left,float Top)
: BView(BRect(Left,Top,Left+B_V_SCROLL_BAR_WIDTH,Top+B_H_SCROLL_BAR_HEIGHT),NULL,B_FOLLOW_RIGHT |
B_FOLLOW_BOTTOM,B_WILL_DRAW)
{
SetHighColor(BeShadow);
SetViewColor(BeInactiveGrey);
}
ScrollViewCorner::~ScrollViewCorner()
{ }
void ScrollViewCorner::Draw(BRect Update)
{
if(Update.bottom >= B_H_SCROLL_BAR_HEIGHT)
StrokeLine(BPoint(0.0,B_H_SCROLL_BAR_HEIGHT),BPoint(B_V_SCROLL_BAR_WIDTH,B_H_SCROLL_BAR_HEIGHT));
if(Update.right >= B_V_SCROLL_BAR_WIDTH)
StrokeLine(BPoint(B_V_SCROLL_BAR_WIDTH,0.0),
BPoint(B_V_SCROLL_BAR_WIDTH,B_H_SCROLL_BAR_HEIGHT-1.0));
}

View File

@ -1,46 +0,0 @@
//*** LICENSE ***
//ColumnListView, its associated classes and source code, and the other components of Santa's Gift Bag are
//being made publicly available and free to use in freeware and shareware products with a price under $25
//(I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products,
//please contact me to negotiate a fee for use. After all, I did work hard on this class and invested a lot
//of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project
//you're working on and how much you expect to make off it. If someone makes money off my work, I'd like to
//get at least a little something. If any of the components of Santa's Gift Bag are is used in a shareware
//or commercial product, I get a free copy. The source is made available so that you can improve and extend
//it as you need. In general it is best to customize your ColumnListView through inheritance, so that you
//can take advantage of enhancements and bug fixes as they become available. Feel free to distribute the
//ColumnListView source, including modified versions, but keep this documentation and license with it.
//*** DESCRIPTION ***
//If you have a BScrollView with horizontal and vertical sliders that isn't
//seated to the lower-right corner of a B_DOCUMENT_WINDOW, there's a "hole"
//between the sliders that needs to be filled. You can use this to fill it.
//In general, it looks best to set the ScrollViewCorner color to
//BeInactiveControlGrey if the vertical BScrollBar is inactive, and the color
//to BeBackgroundGrey if the vertical BScrollBar is active. Have a look at
//Demo3 of ColumnListView to see what I mean if this is unclear.
#ifndef _SGB_SCROLL_VIEW_CORNER_H_
#define _SGB_SCROLL_VIEW_CORNER_H_
//******************************************************************************************************
//**** SYSTEM HEADER FILES
//******************************************************************************************************
#include <View.h>
//******************************************************************************************************
//**** CLASS DECLARATIONS
//******************************************************************************************************
class ScrollViewCorner : public BView
{
public:
ScrollViewCorner(float Left,float Top);
~ScrollViewCorner();
virtual void Draw(BRect Update);
};
#endif

View File

@ -1,525 +0,0 @@
//Name: TextEntryAlert.cpp
//Author: Brian Tietz
//Conventions:
// Global constants (declared with const) and #defines - begin with "c_" followed by lowercase
// words separated by underscores.
// (E.G., #define c_my_constant 5).
// (E.G., const int c_my_constant = 5;).
// Global variables - begin with "g_" followed by lowercase words separated by underscores.
// (E.G., int g_my_global;).
// New data types (classes, structs, typedefs, etc.) - begin with an uppercase letter followed by
// lowercase words separated by uppercase letters. Enumerated constants contain a prefix
// associating them with a particular enumerated set.
// (E.G., typedef int MyTypedef;).
// (E.G., enum MyEnumConst {c_mec_one, c_mec_two};)
// Private member variables - begin with "m_" followed by lowercase words separated by underscores.
// (E.G., int m_my_member;).
// Public or friend-accessible member variables - all lowercase words separated by underscores.
// (E.G., int public_member;).
// Argument and local variables - begin with a lowercase letter followed by
// lowercase words separated by underscores. If the name is already taken by a public member
// variable, prefix with a_ or l_
// (E.G., int my_local; int a_my_arg, int l_my_local).
// Functions (member or global) - begin with an uppercase letter followed by lowercase words
// separated by uppercase letters.
// (E.G., void MyFunction(void);).
//******************************************************************************************************
//**** System header files
//******************************************************************************************************
#include <string.h>
#include <Button.h>
#include <Screen.h>
//******************************************************************************************************
//**** Project header files
//******************************************************************************************************
#include "TextEntryAlert.h"
#include "Colors.h"
#include "NewStrings.h"
//******************************************************************************************************
//**** Constants
//******************************************************************************************************
const float c_text_border_width = 2;
const float c_text_margin = 1;
const float c_item_spacing = 9;
const float c_non_inline_label_spacing = 5;
const float c_inline_label_spacing = 7;
const float c_usual_button_width = 74;
//******************************************************************************************************
//**** BMessage what constants for internal use
//******************************************************************************************************
const uint32 c_button_pressed = 0;
//******************************************************************************************************
//**** TextEntryAlert
//******************************************************************************************************
TextEntryAlert::TextEntryAlert(const char* title, const char* info_text, const char* initial_entry_text,
const char* button_0_label, const char* button_1_label, bool inline_label, float min_text_box_width,
int min_text_box_rows, button_width width_style, bool multi_line, const BRect* frame,
window_look look, window_feel feel, uint32 flags)
: BWindow((frame?*frame:BRect(50,50,60,60)),title,look,feel,flags)
{
//Get unadjusted sizes of the two text boxes
BRect info_text_box;
BRect entry_text_rect;
const char* strings[2] = {info_text?info_text:"",initial_entry_text?initial_entry_text:""};
escapement_delta zero_escapements[2] = {{0,0},{0,0}};
BRect result_rects[2];
be_plain_font->GetBoundingBoxesForStrings(strings,2,B_SCREEN_METRIC,zero_escapements,result_rects);
struct font_height plain_font_height;
be_plain_font->GetHeight(&plain_font_height);
info_text_box = result_rects[0];
info_text_box.bottom = info_text_box.top + ceil(plain_font_height.ascent) +
ceil(plain_font_height.descent);
entry_text_rect = result_rects[1];
entry_text_rect.bottom = entry_text_rect.top +
(ceil(plain_font_height.ascent)+ceil(plain_font_height.descent))*min_text_box_rows +
ceil(plain_font_height.leading)*(min_text_box_rows-1);
entry_text_rect.InsetBy(0-(c_text_margin+c_text_border_width),
0-(c_text_margin+c_text_border_width));
if(entry_text_rect.Width() < min_text_box_width)
entry_text_rect.right = entry_text_rect.left+min_text_box_width;
entry_text_rect.bottom -= 1; //To make it look like BTextControl
//Position and create label
m_label_view = NULL;
if(info_text)
{
info_text_box.OffsetTo(c_item_spacing,c_item_spacing);
if(inline_label)
info_text_box.OffsetBy(0,c_text_border_width+c_text_margin);
else
info_text_box.OffsetBy(c_non_inline_label_spacing,-2);
info_text_box.bottom += 2; //Compensate for offset used by BTextView
info_text_box.right += 1;
m_label_view = new BTextView(info_text_box,NULL,info_text_box.OffsetToCopy(0,0),
B_FOLLOW_LEFT|B_FOLLOW_TOP,B_WILL_DRAW);
m_label_view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
m_label_view->SetText(info_text);
m_label_view->MakeEditable(false);
m_label_view->MakeSelectable(false);
m_label_view->SetWordWrap(false);
}
else
{
info_text_box.Set(0,0,0,0);
inline_label = false;
}
//Create buttons
m_buttons[0] = NULL;
m_buttons[1] = NULL;
BMessage* message;
float button_0_width, button_1_width, buttons_height;
float max_buttons_width = 0;
if(button_0_label != NULL)
{
message = new BMessage(c_button_pressed);
message->AddInt32("which",0);
m_buttons[0] = new BButton(BRect(0,0,0,0),button_0_label,button_0_label,message,B_FOLLOW_LEFT|
B_FOLLOW_BOTTOM);
m_buttons[0]->GetPreferredSize(&button_0_width,&buttons_height);
max_buttons_width = button_0_width;
}
if(button_1_label != NULL)
{
message = new BMessage(c_button_pressed);
message->AddInt32("which",1);
m_buttons[1] = new BButton(BRect(0,0,0,0),button_1_label,button_1_label,message,B_FOLLOW_RIGHT|
B_FOLLOW_BOTTOM);
m_buttons[1]->GetPreferredSize(&button_1_width,&buttons_height);
if(max_buttons_width < button_1_width)
max_buttons_width = button_1_width;
}
//Position and create text entry box
if(inline_label)
entry_text_rect.OffsetTo(info_text_box.right+c_inline_label_spacing,c_item_spacing);
else
entry_text_rect.OffsetTo(c_item_spacing,info_text_box.bottom+c_non_inline_label_spacing-4);
//-5 is to compensate for extra pixels that BeOS adds to the font height
if(frame != NULL)
{
if(entry_text_rect.left + min_text_box_width < frame->Width()-c_item_spacing)
entry_text_rect.right = frame->Width()+c_item_spacing;
else
entry_text_rect.right = entry_text_rect.left + min_text_box_width;
if(min_text_box_rows > 1)
{
float bottom = frame->Height()-c_item_spacing;
if(button_0_label != NULL || button_1_label != NULL)
bottom -= (buttons_height+c_item_spacing);
if(bottom > entry_text_rect.bottom)
entry_text_rect.bottom = bottom;
}
}
m_text_entry_view = new TextEntryAlertTextEntryView(entry_text_rect.InsetByCopy(c_text_border_width,
c_text_border_width),multi_line);
if(initial_entry_text)
m_text_entry_view->SetText(initial_entry_text);
//Position the buttons
if(m_buttons[0] != NULL && m_buttons[1] != NULL)
{
float button_left;
if(inline_label)
button_left = info_text_box.left;
else
button_left = entry_text_rect.left;
m_buttons[0]->MoveTo(button_left,entry_text_rect.bottom+c_item_spacing);
if(width_style == B_WIDTH_AS_USUAL)
m_buttons[0]->ResizeTo(c_usual_button_width,buttons_height);
else if(width_style == B_WIDTH_FROM_LABEL)
m_buttons[0]->ResizeTo(button_0_width,buttons_height);
else //if(width_style == B_WIDTH_FROM_WIDEST)
m_buttons[0]->ResizeTo(max_buttons_width,buttons_height);
}
BButton* right_button = NULL;
if(m_buttons[1] != NULL)
right_button = m_buttons[1];
else if(m_buttons[0] != NULL)
right_button = m_buttons[0];
if(right_button != NULL)
{
if(width_style == B_WIDTH_AS_USUAL)
right_button->ResizeTo(c_usual_button_width,buttons_height);
else if(width_style == B_WIDTH_FROM_LABEL)
right_button->ResizeTo(right_button==m_buttons[1]?button_1_width:button_0_width,
buttons_height);
else //(width_style == B_WIDTH_FROM_WIDEST)
right_button->ResizeTo(max_buttons_width,buttons_height);
right_button->MoveTo(entry_text_rect.right-right_button->Frame().Width()+1,
entry_text_rect.bottom+c_item_spacing);
if(!multi_line)
right_button->MakeDefault(true);
}
//Resize the window
float height;
if(m_buttons[0])
height = m_buttons[0]->Frame().bottom+c_item_spacing-1;
else if(m_buttons[1])
height = m_buttons[1]->Frame().bottom+c_item_spacing-1;
else
height = entry_text_rect.bottom+c_item_spacing-1;
ResizeTo(entry_text_rect.right+c_item_spacing,height);
BRect bounds = Bounds();
if(frame == NULL)
{
BRect screen_frame = BScreen().Frame();
MoveTo(ceil((screen_frame.Width()-bounds.Width())/2),
ceil((screen_frame.Height()-bounds.Height()-19)/2));
}
//Create the background view and add the children
BView* filler = new TextEntryAlertBackgroundView(bounds,entry_text_rect);
if(m_label_view)
filler->AddChild(m_label_view);
filler->AddChild(m_text_entry_view);
if(m_buttons[0])
filler->AddChild(m_buttons[0]);
if(m_buttons[1])
filler->AddChild(m_buttons[1]);
AddChild(filler);
//Complete the setup
m_invoker = NULL;
m_done_mutex = B_ERROR;
m_text_entry_buffer = NULL;
m_button_pressed = NULL;
float min_width = c_item_spacing;
if(m_buttons[0])
min_width += (m_buttons[0]->Frame().Width() + c_item_spacing);
if(m_buttons[1])
min_width += (m_buttons[0]->Frame().Width() + c_item_spacing);
if(min_width < 120)
min_width = 120;
float min_height = entry_text_rect.top;
min_height += (ceil(plain_font_height.ascent)+ceil(plain_font_height.descent));
min_height += ((c_text_margin+c_text_border_width)*2 + c_item_spacing);
if(m_buttons[0] || m_buttons[1])
min_height += (buttons_height + c_item_spacing);
min_width -= 2; //Need this for some reason
min_height -= 2;
SetSizeLimits(min_width,100000,min_height,100000);
AddCommonFilter(new BMessageFilter(B_KEY_DOWN,KeyDownFilterStatic));
m_shortcut[0] = 0;
m_shortcut[1] = 0;
}
TextEntryAlert::~TextEntryAlert()
{
if(m_invoker)
delete m_invoker;
}
int32 TextEntryAlert::Go(char* text_entry_buffer, int32 buffer_size)
{
int32 button_pressed = -1;
m_text_entry_buffer = text_entry_buffer;
m_button_pressed = &button_pressed;
m_buffer_size = buffer_size;
sem_id done_mutex = create_sem(0,"text_entry_alert_done");
m_done_mutex = done_mutex;
if(done_mutex < B_NO_ERROR)
{
Quit();
return -1;
}
m_text_entry_view->MakeFocus(true);
m_text_entry_view->SetMaxBytes(buffer_size);
Show();
acquire_sem(done_mutex);
delete_sem(done_mutex);
return button_pressed;
}
status_t TextEntryAlert::Go(BInvoker *invoker)
{
m_invoker = invoker;
m_text_entry_view->MakeFocus(true);
Show();
return B_NO_ERROR;
}
void TextEntryAlert::SetShortcut(int32 index, char shortcut)
{
m_shortcut[index] = shortcut;
}
char TextEntryAlert::Shortcut(int32 index) const
{
return m_shortcut[index];
}
filter_result TextEntryAlert::KeyDownFilterStatic(BMessage* message, BHandler** target,
BMessageFilter* filter)
{
return ((TextEntryAlert*)filter->Looper())->KeyDownFilter(message);
}
filter_result TextEntryAlert::KeyDownFilter(BMessage *message)
{
if(message->what == B_KEY_DOWN)
{
char byte;
if(message->FindInt8("byte",(int8*)&byte) == B_NO_ERROR && !message->HasInt8("byte",1))
{
char space = B_SPACE;
if(m_shortcut[0] && byte == m_shortcut[0])
{
m_buttons[0]->KeyDown(&space,1);
return B_SKIP_MESSAGE;
}
else if(m_shortcut[1] && byte == m_shortcut[1])
{
m_buttons[1]->KeyDown(&space,1);
return B_SKIP_MESSAGE;
}
}
}
return B_DISPATCH_MESSAGE;
}
BTextView* TextEntryAlert::LabelView(void) const
{
return m_label_view;
}
BTextView* TextEntryAlert::TextEntryView(void) const
{
return m_text_entry_view;
}
void TextEntryAlert::SetTabAllowed(bool allow)
{
m_text_entry_view->SetTabAllowed(allow);
}
bool TextEntryAlert::TabAllowed()
{
return m_text_entry_view->TabAllowed();
}
void TextEntryAlert::MessageReceived(BMessage* message)
{
if(message->what == c_button_pressed)
{
int32 which;
if(message->FindInt32("which",&which) == B_NO_ERROR)
{
const char* text = m_text_entry_view->Text();
if(text == NULL)
text = "";
if(m_done_mutex < B_NO_ERROR)
{
//Asynchronous version: add the necessary fields
BMessage* message = m_invoker->Message();
if(message && (message->AddInt32("which",which) == B_NO_ERROR ||
message->ReplaceInt32("which",which) == B_NO_ERROR) &&
(message->AddString("entry_text",text) == B_NO_ERROR ||
message->ReplaceString("entry_text",text) == B_NO_ERROR))
m_invoker->Invoke();
}
else
{
//Synchronous version: set the result button and text buffer, then release the thread
//that created me
*m_button_pressed = which;
if(m_text_entry_buffer)
Strtcpy(m_text_entry_buffer,text,m_buffer_size);
release_sem(m_done_mutex);
m_done_mutex = B_ERROR;
}
PostMessage(B_QUIT_REQUESTED);
}
}
}
void TextEntryAlert::Quit()
{
//Release the mutex if I'm synchronous and I haven't released it yet
if(m_done_mutex >= B_NO_ERROR)
release_sem(m_done_mutex);
BWindow::Quit();
}
//******************************************************************************************************
//**** TextEntryAlertBackgroundView
//******************************************************************************************************
TextEntryAlertBackgroundView::TextEntryAlertBackgroundView(BRect frame, BRect entry_text_rect)
: BView(frame,NULL,B_FOLLOW_ALL_SIDES,B_WILL_DRAW|B_FRAME_EVENTS)
{
m_entry_text_rect = entry_text_rect;
m_cached_bounds = Bounds();
rgb_color background_color = ui_color(B_PANEL_BACKGROUND_COLOR);
m_dark_1_color = tint_color(background_color,B_DARKEN_1_TINT);
m_dark_2_color = tint_color(background_color,B_DARKEN_4_TINT);
SetViewColor(background_color);
SetDrawingMode(B_OP_COPY);
}
void TextEntryAlertBackgroundView::Draw(BRect update_rect)
{
if(update_rect.Intersects(m_entry_text_rect))
{
SetHighColor(m_dark_1_color);
StrokeLine(BPoint(m_entry_text_rect.left,m_entry_text_rect.top),
BPoint(m_entry_text_rect.right,m_entry_text_rect.top));
StrokeLine(BPoint(m_entry_text_rect.left,m_entry_text_rect.top+1),
BPoint(m_entry_text_rect.left,m_entry_text_rect.bottom));
SetHighColor(White);
StrokeLine(BPoint(m_entry_text_rect.right,m_entry_text_rect.top+1),
BPoint(m_entry_text_rect.right,m_entry_text_rect.bottom-1));
StrokeLine(BPoint(m_entry_text_rect.left+1,m_entry_text_rect.bottom),
BPoint(m_entry_text_rect.right,m_entry_text_rect.bottom));
SetHighColor(m_dark_2_color);
StrokeLine(BPoint(m_entry_text_rect.left+1,m_entry_text_rect.top+1),
BPoint(m_entry_text_rect.right-1,m_entry_text_rect.top+1));
StrokeLine(BPoint(m_entry_text_rect.left+1,m_entry_text_rect.top+2),
BPoint(m_entry_text_rect.left+1,m_entry_text_rect.bottom-1));
}
}
void TextEntryAlertBackgroundView::FrameResized(float width, float heigh)
{
BRect new_bounds = Bounds();
float width_delta = new_bounds.right - m_cached_bounds.right;
float height_delta = new_bounds.bottom - m_cached_bounds.bottom;
BRect new_entry_text_rect = m_entry_text_rect;
new_entry_text_rect.right += width_delta;
new_entry_text_rect.bottom += height_delta;
float right_min = m_entry_text_rect.right;
if(right_min > new_entry_text_rect.right)
right_min = new_entry_text_rect.right;
float right_max = m_entry_text_rect.right;
if(right_max < new_entry_text_rect.right)
right_max = new_entry_text_rect.right;
float bottom_min = m_entry_text_rect.bottom;
if(bottom_min > new_entry_text_rect.bottom)
bottom_min = new_entry_text_rect.bottom;
float bottom_max = m_entry_text_rect.bottom;
if(bottom_max < new_entry_text_rect.bottom)
bottom_max = new_entry_text_rect.bottom;
if(new_entry_text_rect.right != m_entry_text_rect.right)
Invalidate(BRect(right_min-1,new_entry_text_rect.top,right_max,bottom_max));
if(new_entry_text_rect.bottom != m_entry_text_rect.bottom)
Invalidate(BRect(new_entry_text_rect.left,bottom_min-1,right_max,bottom_max));
m_entry_text_rect = new_entry_text_rect;
m_cached_bounds = new_bounds;
}
//******************************************************************************************************
//**** TextEntryAlertTextEntryView
//******************************************************************************************************
TextEntryAlertTextEntryView::TextEntryAlertTextEntryView(BRect frame, bool multi_line)
: BTextView(frame,NULL,frame.OffsetToCopy(0,0).InsetByCopy(c_text_margin,c_text_margin),
multi_line?B_FOLLOW_ALL_SIDES:B_FOLLOW_LEFT_RIGHT,B_WILL_DRAW|B_NAVIGABLE)
{
m_tab_allowed = false;
m_multi_line = multi_line;
SetViewColor(White);
SetWordWrap(true);
}
void TextEntryAlertTextEntryView::SetTabAllowed(bool allow)
{
m_tab_allowed = allow;
}
void TextEntryAlertTextEntryView::KeyDown(const char* bytes, int32 num_bytes)
{
if(num_bytes == 1 && (bytes[0] == B_TAB && (!m_tab_allowed)) || (bytes[0] == B_ENTER && (!m_multi_line)))
{
BView::KeyDown(bytes,num_bytes);
return;
}
BTextView::KeyDown(bytes,num_bytes);
}
void TextEntryAlertTextEntryView::AttachedToWindow()
{
BTextView::AttachedToWindow();
const char* text = Text();
if(text)
{
int32 length = strlen(text);
Select(length,length);
}
}

View File

@ -1,165 +0,0 @@
//Name: TextEntryAlert.h
//Author: Brian Tietz
//Conventions:
// Global constants (declared with const) and #defines - begin with "c_" followed by lowercase
// words separated by underscores.
// (E.G., #define c_my_constant 5).
// (E.G., const int c_my_constant = 5;).
// Global variables - begin with "g_" followed by lowercase words separated by underscores.
// (E.G., int g_my_global;).
// New data types (classes, structs, typedefs, etc.) - begin with an uppercase letter followed by
// lowercase words separated by uppercase letters. Enumerated constants contain a prefix
// associating them with a particular enumerated set.
// (E.G., typedef int MyTypedef;).
// (E.G., enum MyEnumConst {c_mec_one, c_mec_two};)
// Private member variables - begin with "m_" followed by lowercase words separated by underscores.
// (E.G., int m_my_member;).
// Public or friend-accessible member variables - all lowercase words separated by underscores.
// (E.G., int public_member;).
// Argument and local variables - begin with a lowercase letter followed by
// lowercase words separated by underscores. If the name is already taken by a public member
// variable, prefix with a_ or l_
// (E.G., int my_local; int a_my_arg, int l_my_local).
// Functions (member or global) - begin with an uppercase letter followed by lowercase words
// separated by uppercase letters.
// (E.G., void MyFunction(void);).
#ifndef _TEXT_ENTRY_ALERT_H_
#define _TEXT_ENTRY_ALERT_H_
//******************************************************************************************************
//**** System header files
//******************************************************************************************************
#include <Window.h>
#include <TextView.h>
#include <MessageFilter.h>
//******************************************************************************************************
//**** Forward name declarations
//******************************************************************************************************
class TextEntryAlertTextEntryView;
//******************************************************************************************************
//**** TextEntryAlert
//******************************************************************************************************
class TextEntryAlert : public BWindow
{
public:
TextEntryAlert(const char* title, const char* info_text, const char* initial_entry_text,
const char* button_0_label, const char* button_1_label = NULL,
bool inline_label = true, float min_text_box_width = 120, int min_text_box_rows = 1,
button_width width_style = B_WIDTH_AS_USUAL, bool multi_line = false,
const BRect* frame = NULL, window_look look = B_MODAL_WINDOW_LOOK,
window_feel feel = B_MODAL_APP_WINDOW_FEEL,
uint32 flags = B_NOT_RESIZABLE|B_ASYNCHRONOUS_CONTROLS);
//The title is not displayed unless you use a window_look other than the default. info_text
//is the label applied to the text entry box. If inline_label is true, then the label is
//placed to the left of the text entry box, otherwise it is placed above it. If a frame is
//not specified, the TextEntryAlert will be auto-sized and auto-positioned to accommodate
//the text. The minimum text entry box size can be specified using min_text_box_width and
//text_box_rows. Multi-line specifies whether the user can hit return and enter multiple
//lines of text, regardless of the height of the text box.
~TextEntryAlert();
int32 Go(char* text_entry_buffer, int32 buffer_size);
//Synchronous version: The function doesn't return until the user has clicked a button and
//the panel has been removed from the screen. The value it returns is the index of
//the clicked button (0 or 1, left-to-right). The user-entered (or unchanged) text is
//stored in text_entry_buffer. The TextEntryAlert is deleted before it returns, and should
//be considered invalid after Go is called. If the TextEntryAlert is sent a
//B_QUIT_REQUESTED message while the panel is still on-screen, it returns -1.
status_t Go(BInvoker* invoker);
//Asynchronous version: The function returns immediately (with B_OK) and the button index is
//delivered as the int32 "which" field of the BMessage that's sent to the BInvoker's target,
//and the text message is delivered as the string "entry_text" field of the BMessage. The
//TextEntryBox will take posession of the BInvoker and delete it when finished. The
//TextEntryAlert is deleted when the user hits any of the buttons, and should be considered
//invalid after Go is called. If the TextEntryAlert is sent a B_QUIT_REQUESTED message
//while the panel is still on-screen, it suppresses sending of the message.
void SetShortcut(int32 index, char shortcut);
char Shortcut(int32 index) const;
//These functions set and return the shortcut character that's mapped to the button at
//index. A given button can have only one shortcut except for the rightmost button, which,
//in addition to the shortcut that you give it here, is always mapped to B_ENTER. If you
//create a "Cancel" button, you should give it a shortcut of B_ESCAPE. If multi_line was
//specified as true in the TextEntryAlert constructor, no shortcuts are allowed, including
//the built-in B_ENTER shortcut on the rightmost button.
void SetTabAllowed(bool allow);
//By default, tab is not allowed, being used for navigation instead. Set this to true to
//allow the user to actually enter a tab character in the text entry box.
bool TabAllowed();
BTextView* LabelView(void) const;
BTextView* TextEntryView(void) const;
//Returns a pointer to the BTextView object that contains the textual information or the
//user-editable text that's displayed in the panel, respectively. You can fiddle with these
//objects but you mustn't delete them.
//BWindow overrides
virtual void MessageReceived(BMessage* message);
virtual void Quit();
private:
BTextView* m_label_view;
TextEntryAlertTextEntryView* m_text_entry_view;
static filter_result KeyDownFilterStatic(BMessage* message, BHandler** target,
BMessageFilter* filter);
filter_result KeyDownFilter(BMessage* message);
BButton* m_buttons[2];
char m_shortcut[2];
//For the synchronous version (pointers point to data areas owned by thread that called Go)
sem_id m_done_mutex; //Mutex to release when the user hits a button or the window closes
char* m_text_entry_buffer; //Buffer to store the user-entered text when the user hits a button
int32* m_button_pressed; //Place to store the button index that the user hit
int32 m_buffer_size;
//For the asynchronous version
BInvoker *m_invoker; //I own this object and will delete it when done.
};
//******************************************************************************************************
//**** TextEntryAlertBackgroundView
//******************************************************************************************************
class TextEntryAlertBackgroundView : public BView
{
public:
TextEntryAlertBackgroundView(BRect frame, BRect entry_text_rect);
virtual void Draw(BRect update_rect);
virtual void FrameResized(float width, float heigh);
private:
BRect m_entry_text_rect;
BRect m_cached_bounds;
rgb_color m_dark_1_color;
rgb_color m_dark_2_color;
};
//******************************************************************************************************
//**** TextEntryAlertTextEntryView
//******************************************************************************************************
class TextEntryAlertTextEntryView : public BTextView
{
public:
TextEntryAlertTextEntryView(BRect frame, bool multi_line);
void SetTabAllowed(bool allow);
inline bool TabAllowed() {return m_tab_allowed;}
virtual void KeyDown(const char* bytes, int32 num_bytes);
virtual void AttachedToWindow();
private:
bool m_tab_allowed;
bool m_multi_line;
};
#endif //_TEXT_ENTRY_ALERT_H_