* Removed no longer needed workaround for mouse wheel messages (thanks Axel!).
* Introduced SourceCode::LineLengthAt(index) and respective implementations in FileSourceCode and DisassembledCode for getting the cached length of the line at the given index. * Use LineLengthAt in various places in SourceView::TextView to avoid having to calculate string lengths on the fly. * Clamp the size of the drag and drop rect to the window size. Otherwise in cases of large selections, said rect would get quite large. * Add support for double click word and triple click line selection. * Fix problems with tracking state which would erroneously cause the mouse entering the view while dragging on a scroll bar to initiate a drag and drop if there was selected text. * Add Select All menu/keyboard shortcut and implement corresponding functionality in SourceView::TextView. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31587 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -98,7 +98,7 @@ SourceFile::Init(const char* path)
|
||||
fLineCount++;
|
||||
|
||||
// allocate line offset array
|
||||
fLineOffsets = new(std::nothrow) int32[fLineCount];
|
||||
fLineOffsets = new(std::nothrow) int32[fLineCount + 1];
|
||||
if (fLineOffsets == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
@@ -111,6 +111,7 @@ SourceFile::Init(const char* path)
|
||||
fLineOffsets[lineIndex++] = i + 1;
|
||||
}
|
||||
}
|
||||
fLineOffsets[fLineCount] = fileSize - 1;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -131,6 +132,13 @@ SourceFile::LineAt(int32 index) const
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
SourceFile::LineLengthAt(int32 index) const
|
||||
{
|
||||
return index >= 0 && index < fLineCount
|
||||
? fLineOffsets[index + 1] - fLineOffsets[index] - 1: 0;
|
||||
}
|
||||
|
||||
void
|
||||
SourceFile::LastReferenceReleased()
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
|
||||
int32 CountLines() const;
|
||||
const char* LineAt(int32 index) const;
|
||||
int32 LineLengthAt(int32 index) const;
|
||||
|
||||
protected:
|
||||
virtual void LastReferenceReleased();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Clipboard.h>
|
||||
@@ -227,10 +228,22 @@ private:
|
||||
offset = _offset;
|
||||
}
|
||||
|
||||
bool operator==(const SelectionPoint& other)
|
||||
{
|
||||
return line == other.line && offset == other.offset;
|
||||
}
|
||||
|
||||
int32 line;
|
||||
int32 offset;
|
||||
};
|
||||
|
||||
enum TrackingState
|
||||
{
|
||||
kNotTracking = 0,
|
||||
kTracking = 1,
|
||||
kDragging = 2
|
||||
};
|
||||
|
||||
float _MaxLineWidth();
|
||||
void _FormatLine(const char* line,
|
||||
BString& formattedLine);
|
||||
@@ -238,6 +251,8 @@ private:
|
||||
void _GetSelectionRegion(BRegion& region) const;
|
||||
void _GetSelectionText(BString& text) const;
|
||||
void _CopySelectionToClipboard() const;
|
||||
void _SelectWordAt(const SelectionPoint& point);
|
||||
void _SelectLineAt(const SelectionPoint& point);
|
||||
|
||||
private:
|
||||
|
||||
@@ -246,8 +261,11 @@ private:
|
||||
SelectionPoint fSelectionStart;
|
||||
SelectionPoint fSelectionEnd;
|
||||
SelectionPoint fSelectionBase;
|
||||
bigtime_t fLastClickTime;
|
||||
int16 fClickCount;
|
||||
rgb_color fTextColor;
|
||||
bool fSelectionMode;
|
||||
TrackingState fTrackState;
|
||||
};
|
||||
|
||||
|
||||
@@ -838,7 +856,10 @@ SourceView::TextView::TextView(SourceView* sourceView, FontInfo* fontInfo)
|
||||
fSelectionStart(-1, -1),
|
||||
fSelectionEnd(-1, -1),
|
||||
fSelectionBase(-1, -1),
|
||||
fSelectionMode(false)
|
||||
fLastClickTime(0),
|
||||
fClickCount(0),
|
||||
fSelectionMode(false),
|
||||
fTrackState(kNotTracking)
|
||||
{
|
||||
SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
|
||||
fTextColor = ui_color(B_DOCUMENT_TEXT_COLOR);
|
||||
@@ -958,8 +979,13 @@ SourceView::TextView::MessageReceived(BMessage* message)
|
||||
_CopySelectionToClipboard();
|
||||
break;
|
||||
|
||||
case B_MOUSE_WHEEL_CHANGED:
|
||||
fSourceView->MessageReceived(message);
|
||||
case B_SELECT_ALL:
|
||||
fSelectionStart.line = 0;
|
||||
fSelectionStart.offset = 0;
|
||||
fSelectionEnd.line = fSourceCode->CountLines() - 1;
|
||||
fSelectionEnd.offset = fSourceCode->LineLengthAt(
|
||||
fSelectionEnd.line);
|
||||
Invalidate();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -975,13 +1001,35 @@ SourceView::TextView::MouseDown(BPoint where)
|
||||
if (fSourceCode != NULL) {
|
||||
if (!IsFocus())
|
||||
MakeFocus(true);
|
||||
fTrackState = kTracking;
|
||||
|
||||
// don't reset the selection if the user clicks within the
|
||||
// current selection range
|
||||
BRegion region;
|
||||
_GetSelectionRegion(region);
|
||||
if (!region.Contains(where)) {
|
||||
SelectionPoint point = _SelectionPointAt(where);
|
||||
bigtime_t clickTime = system_time();
|
||||
SelectionPoint point = _SelectionPointAt(where);
|
||||
bigtime_t clickSpeed = 0;
|
||||
get_click_speed(&clickSpeed);
|
||||
if (clickTime - fLastClickTime < clickSpeed
|
||||
&& fSelectionBase == point) {
|
||||
if (fClickCount > 3) {
|
||||
fClickCount = 0;
|
||||
fLastClickTime = 0;
|
||||
} else {
|
||||
fClickCount++;
|
||||
fLastClickTime = clickTime;
|
||||
}
|
||||
} else {
|
||||
fClickCount = 1;
|
||||
fLastClickTime = clickTime;
|
||||
}
|
||||
|
||||
if (fClickCount == 2)
|
||||
_SelectWordAt(point);
|
||||
else if (fClickCount == 3) {
|
||||
_SelectLineAt(point);
|
||||
} else if (!region.Contains(where)) {
|
||||
fSelectionBase = fSelectionStart = fSelectionEnd = point;
|
||||
fSelectionMode = true;
|
||||
Invalidate();
|
||||
@@ -1023,7 +1071,7 @@ SourceView::TextView::MouseMoved(BPoint where, uint32 transit,
|
||||
_GetSelectionRegion(region);
|
||||
region.Include(&oldRegion);
|
||||
Invalidate(®ion);
|
||||
} else {
|
||||
} else if (fTrackState == kTracking) {
|
||||
_GetSelectionRegion(region);
|
||||
if (region.CountRects() > 0) {
|
||||
BString text;
|
||||
@@ -1035,7 +1083,18 @@ SourceView::TextView::MouseMoved(BPoint where, uint32 transit,
|
||||
clipName << " clipping";
|
||||
message.AddString ("be:clip_name", clipName.String());
|
||||
message.AddInt32 ("be:actions", B_COPY_TARGET);
|
||||
DragMessage(&message, region.Frame());
|
||||
BRect dragRect = region.Frame();
|
||||
BRect visibleRect = fSourceView->Bounds();
|
||||
if (dragRect.Height() > visibleRect.Height()) {
|
||||
dragRect.top = 0;
|
||||
dragRect.bottom = visibleRect.Height();
|
||||
}
|
||||
if (dragRect.Width() > visibleRect.Width()) {
|
||||
dragRect.left = 0;
|
||||
dragRect.right = visibleRect.Width();
|
||||
}
|
||||
DragMessage(&message, dragRect);
|
||||
fTrackState = kDragging;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1045,6 +1104,7 @@ void
|
||||
SourceView::TextView::MouseUp(BPoint where)
|
||||
{
|
||||
fSelectionMode = false;
|
||||
fTrackState = kNotTracking;
|
||||
}
|
||||
|
||||
|
||||
@@ -1090,7 +1150,7 @@ SourceView::TextView::_SelectionPointAt(BPoint where) const
|
||||
int32 line = LineAtOffset(where.y);
|
||||
int32 offset = (int32)max_c((where.x - kLeftTextMargin)
|
||||
/ fCharacterWidth, 0);
|
||||
int32 lineLength = strlen(fSourceCode->LineAt(line));
|
||||
int32 lineLength = fSourceCode->LineLengthAt(line);
|
||||
if (offset > lineLength)
|
||||
offset = (lineLength > 0) ? lineLength - 1 : 0;
|
||||
return SelectionPoint(line, offset);
|
||||
@@ -1184,6 +1244,48 @@ SourceView::TextView::_CopySelectionToClipboard(void) const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceView::TextView::_SelectWordAt(const SelectionPoint& point)
|
||||
{
|
||||
const char* line = fSourceCode->LineAt(point.line);
|
||||
if (isalpha(line[point.offset]) || isdigit(line[point.offset])) {
|
||||
int32 length = fSourceCode->LineLengthAt(point.line);
|
||||
int32 start = point.offset - 1;
|
||||
int32 end = point.offset + 1;
|
||||
while ((end) < length) {
|
||||
if (!isalpha(line[end]) && !isdigit(line[end]))
|
||||
break;
|
||||
++end;
|
||||
}
|
||||
while ((start - 1) >= 0) {
|
||||
if (!isalpha(line[start - 1]) && !isdigit(line[start - 1]))
|
||||
break;
|
||||
--start;
|
||||
}
|
||||
|
||||
fSelectionStart.line = point.line;
|
||||
fSelectionStart.offset = start;
|
||||
fSelectionEnd.line = point.line;
|
||||
fSelectionEnd.offset = end;
|
||||
BRegion region;
|
||||
_GetSelectionRegion(region);
|
||||
Invalidate(®ion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceView::TextView::_SelectLineAt(const SelectionPoint& point)
|
||||
{
|
||||
fSelectionStart.line = fSelectionEnd.line = point.line;
|
||||
fSelectionStart.offset = 0;
|
||||
fSelectionEnd.offset = fSourceCode->LineLengthAt(point.line);
|
||||
BRegion region;
|
||||
_GetSelectionRegion(region);
|
||||
Invalidate(®ion);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - SourceView
|
||||
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ TeamWindow::DispatchMessage(BMessage* message, BHandler* handler)
|
||||
break;
|
||||
|
||||
case B_COPY:
|
||||
case B_SELECT_ALL:
|
||||
BView* focusView = CurrentFocus();
|
||||
if (focusView != NULL)
|
||||
focusView->MessageReceived(message);
|
||||
@@ -413,6 +414,9 @@ TeamWindow::_Init()
|
||||
item = new BMenuItem("Copy", new BMessage(B_COPY), 'C');
|
||||
menu->AddItem(item);
|
||||
item->SetTarget(this);
|
||||
item = new BMenuItem("Select All", new BMessage(B_SELECT_ALL), 'A');
|
||||
menu->AddItem(item);
|
||||
item->SetTarget(this);
|
||||
|
||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||
_UpdateRunButtons();
|
||||
|
||||
@@ -84,6 +84,14 @@ DisassembledCode::LineAt(int32 index) const
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
DisassembledCode::LineLengthAt(int32 index) const
|
||||
{
|
||||
Line* line = fLines.ItemAt(index);
|
||||
return line != NULL ? line->line.Length() : 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DisassembledCode::GetStatementLocationRange(const SourceLocation& location,
|
||||
SourceLocation& _start, SourceLocation& _end) const
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
|
||||
virtual int32 CountLines() const;
|
||||
virtual const char* LineAt(int32 index) const;
|
||||
virtual int32 LineLengthAt(int32 index) const;
|
||||
|
||||
virtual bool GetStatementLocationRange(
|
||||
const SourceLocation& location,
|
||||
|
||||
@@ -91,6 +91,13 @@ FileSourceCode::LineAt(int32 index) const
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
FileSourceCode::LineLengthAt(int32 index) const
|
||||
{
|
||||
return fSourceFile->LineLengthAt(index);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FileSourceCode::GetStatementLocationRange(const SourceLocation& location,
|
||||
SourceLocation& _start, SourceLocation& _end) const
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
|
||||
virtual int32 CountLines() const;
|
||||
virtual const char* LineAt(int32 index) const;
|
||||
virtual int32 LineLengthAt(int32 index) const;
|
||||
|
||||
virtual bool GetStatementLocationRange(
|
||||
const SourceLocation& location,
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
|
||||
virtual int32 CountLines() const = 0;
|
||||
virtual const char* LineAt(int32 index) const = 0;
|
||||
virtual int32 LineLengthAt(int32 index) const = 0;
|
||||
|
||||
virtual bool GetStatementLocationRange(
|
||||
const SourceLocation& location,
|
||||
|
||||
Reference in New Issue
Block a user