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:
parent
09c9c0c147
commit
10cde11f08
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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(®ion);
|
||||
view->DrawBitmap(bitmap,iconBounds);
|
||||
}
|
||||
delete bitmap;
|
||||
}
|
||||
fCachedRect = header_rect;
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
|
||||
}
|
@ -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
@ -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
|
@ -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;
|
||||
|
@ -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_
|
@ -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
|
||||
};
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
@ -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
|
@ -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()
|
||||
{ }
|
@ -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
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_
|
Loading…
Reference in New Issue
Block a user