* 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++;
|
fLineCount++;
|
||||||
|
|
||||||
// allocate line offset array
|
// allocate line offset array
|
||||||
fLineOffsets = new(std::nothrow) int32[fLineCount];
|
fLineOffsets = new(std::nothrow) int32[fLineCount + 1];
|
||||||
if (fLineOffsets == NULL)
|
if (fLineOffsets == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -111,6 +111,7 @@ SourceFile::Init(const char* path)
|
|||||||
fLineOffsets[lineIndex++] = i + 1;
|
fLineOffsets[lineIndex++] = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fLineOffsets[fLineCount] = fileSize - 1;
|
||||||
|
|
||||||
return B_OK;
|
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
|
void
|
||||||
SourceFile::LastReferenceReleased()
|
SourceFile::LastReferenceReleased()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public:
|
|||||||
|
|
||||||
int32 CountLines() const;
|
int32 CountLines() const;
|
||||||
const char* LineAt(int32 index) const;
|
const char* LineAt(int32 index) const;
|
||||||
|
int32 LineLengthAt(int32 index) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void LastReferenceReleased();
|
virtual void LastReferenceReleased();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <Clipboard.h>
|
#include <Clipboard.h>
|
||||||
@@ -227,10 +228,22 @@ private:
|
|||||||
offset = _offset;
|
offset = _offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(const SelectionPoint& other)
|
||||||
|
{
|
||||||
|
return line == other.line && offset == other.offset;
|
||||||
|
}
|
||||||
|
|
||||||
int32 line;
|
int32 line;
|
||||||
int32 offset;
|
int32 offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TrackingState
|
||||||
|
{
|
||||||
|
kNotTracking = 0,
|
||||||
|
kTracking = 1,
|
||||||
|
kDragging = 2
|
||||||
|
};
|
||||||
|
|
||||||
float _MaxLineWidth();
|
float _MaxLineWidth();
|
||||||
void _FormatLine(const char* line,
|
void _FormatLine(const char* line,
|
||||||
BString& formattedLine);
|
BString& formattedLine);
|
||||||
@@ -238,6 +251,8 @@ private:
|
|||||||
void _GetSelectionRegion(BRegion& region) const;
|
void _GetSelectionRegion(BRegion& region) const;
|
||||||
void _GetSelectionText(BString& text) const;
|
void _GetSelectionText(BString& text) const;
|
||||||
void _CopySelectionToClipboard() const;
|
void _CopySelectionToClipboard() const;
|
||||||
|
void _SelectWordAt(const SelectionPoint& point);
|
||||||
|
void _SelectLineAt(const SelectionPoint& point);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -246,8 +261,11 @@ private:
|
|||||||
SelectionPoint fSelectionStart;
|
SelectionPoint fSelectionStart;
|
||||||
SelectionPoint fSelectionEnd;
|
SelectionPoint fSelectionEnd;
|
||||||
SelectionPoint fSelectionBase;
|
SelectionPoint fSelectionBase;
|
||||||
|
bigtime_t fLastClickTime;
|
||||||
|
int16 fClickCount;
|
||||||
rgb_color fTextColor;
|
rgb_color fTextColor;
|
||||||
bool fSelectionMode;
|
bool fSelectionMode;
|
||||||
|
TrackingState fTrackState;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -838,7 +856,10 @@ SourceView::TextView::TextView(SourceView* sourceView, FontInfo* fontInfo)
|
|||||||
fSelectionStart(-1, -1),
|
fSelectionStart(-1, -1),
|
||||||
fSelectionEnd(-1, -1),
|
fSelectionEnd(-1, -1),
|
||||||
fSelectionBase(-1, -1),
|
fSelectionBase(-1, -1),
|
||||||
fSelectionMode(false)
|
fLastClickTime(0),
|
||||||
|
fClickCount(0),
|
||||||
|
fSelectionMode(false),
|
||||||
|
fTrackState(kNotTracking)
|
||||||
{
|
{
|
||||||
SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
|
SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
|
||||||
fTextColor = ui_color(B_DOCUMENT_TEXT_COLOR);
|
fTextColor = ui_color(B_DOCUMENT_TEXT_COLOR);
|
||||||
@@ -958,8 +979,13 @@ SourceView::TextView::MessageReceived(BMessage* message)
|
|||||||
_CopySelectionToClipboard();
|
_CopySelectionToClipboard();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_MOUSE_WHEEL_CHANGED:
|
case B_SELECT_ALL:
|
||||||
fSourceView->MessageReceived(message);
|
fSelectionStart.line = 0;
|
||||||
|
fSelectionStart.offset = 0;
|
||||||
|
fSelectionEnd.line = fSourceCode->CountLines() - 1;
|
||||||
|
fSelectionEnd.offset = fSourceCode->LineLengthAt(
|
||||||
|
fSelectionEnd.line);
|
||||||
|
Invalidate();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -975,13 +1001,35 @@ SourceView::TextView::MouseDown(BPoint where)
|
|||||||
if (fSourceCode != NULL) {
|
if (fSourceCode != NULL) {
|
||||||
if (!IsFocus())
|
if (!IsFocus())
|
||||||
MakeFocus(true);
|
MakeFocus(true);
|
||||||
|
fTrackState = kTracking;
|
||||||
|
|
||||||
// don't reset the selection if the user clicks within the
|
// don't reset the selection if the user clicks within the
|
||||||
// current selection range
|
// current selection range
|
||||||
BRegion region;
|
BRegion region;
|
||||||
_GetSelectionRegion(region);
|
_GetSelectionRegion(region);
|
||||||
if (!region.Contains(where)) {
|
bigtime_t clickTime = system_time();
|
||||||
SelectionPoint point = _SelectionPointAt(where);
|
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;
|
fSelectionBase = fSelectionStart = fSelectionEnd = point;
|
||||||
fSelectionMode = true;
|
fSelectionMode = true;
|
||||||
Invalidate();
|
Invalidate();
|
||||||
@@ -1023,7 +1071,7 @@ SourceView::TextView::MouseMoved(BPoint where, uint32 transit,
|
|||||||
_GetSelectionRegion(region);
|
_GetSelectionRegion(region);
|
||||||
region.Include(&oldRegion);
|
region.Include(&oldRegion);
|
||||||
Invalidate(®ion);
|
Invalidate(®ion);
|
||||||
} else {
|
} else if (fTrackState == kTracking) {
|
||||||
_GetSelectionRegion(region);
|
_GetSelectionRegion(region);
|
||||||
if (region.CountRects() > 0) {
|
if (region.CountRects() > 0) {
|
||||||
BString text;
|
BString text;
|
||||||
@@ -1035,7 +1083,18 @@ SourceView::TextView::MouseMoved(BPoint where, uint32 transit,
|
|||||||
clipName << " clipping";
|
clipName << " clipping";
|
||||||
message.AddString ("be:clip_name", clipName.String());
|
message.AddString ("be:clip_name", clipName.String());
|
||||||
message.AddInt32 ("be:actions", B_COPY_TARGET);
|
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)
|
SourceView::TextView::MouseUp(BPoint where)
|
||||||
{
|
{
|
||||||
fSelectionMode = false;
|
fSelectionMode = false;
|
||||||
|
fTrackState = kNotTracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1090,7 +1150,7 @@ SourceView::TextView::_SelectionPointAt(BPoint where) const
|
|||||||
int32 line = LineAtOffset(where.y);
|
int32 line = LineAtOffset(where.y);
|
||||||
int32 offset = (int32)max_c((where.x - kLeftTextMargin)
|
int32 offset = (int32)max_c((where.x - kLeftTextMargin)
|
||||||
/ fCharacterWidth, 0);
|
/ fCharacterWidth, 0);
|
||||||
int32 lineLength = strlen(fSourceCode->LineAt(line));
|
int32 lineLength = fSourceCode->LineLengthAt(line);
|
||||||
if (offset > lineLength)
|
if (offset > lineLength)
|
||||||
offset = (lineLength > 0) ? lineLength - 1 : 0;
|
offset = (lineLength > 0) ? lineLength - 1 : 0;
|
||||||
return SelectionPoint(line, offset);
|
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
|
// #pragma mark - SourceView
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ TeamWindow::DispatchMessage(BMessage* message, BHandler* handler)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case B_COPY:
|
case B_COPY:
|
||||||
|
case B_SELECT_ALL:
|
||||||
BView* focusView = CurrentFocus();
|
BView* focusView = CurrentFocus();
|
||||||
if (focusView != NULL)
|
if (focusView != NULL)
|
||||||
focusView->MessageReceived(message);
|
focusView->MessageReceived(message);
|
||||||
@@ -413,6 +414,9 @@ TeamWindow::_Init()
|
|||||||
item = new BMenuItem("Copy", new BMessage(B_COPY), 'C');
|
item = new BMenuItem("Copy", new BMessage(B_COPY), 'C');
|
||||||
menu->AddItem(item);
|
menu->AddItem(item);
|
||||||
item->SetTarget(this);
|
item->SetTarget(this);
|
||||||
|
item = new BMenuItem("Select All", new BMessage(B_SELECT_ALL), 'A');
|
||||||
|
menu->AddItem(item);
|
||||||
|
item->SetTarget(this);
|
||||||
|
|
||||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||||
_UpdateRunButtons();
|
_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
|
bool
|
||||||
DisassembledCode::GetStatementLocationRange(const SourceLocation& location,
|
DisassembledCode::GetStatementLocationRange(const SourceLocation& location,
|
||||||
SourceLocation& _start, SourceLocation& _end) const
|
SourceLocation& _start, SourceLocation& _end) const
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public:
|
|||||||
|
|
||||||
virtual int32 CountLines() const;
|
virtual int32 CountLines() const;
|
||||||
virtual const char* LineAt(int32 index) const;
|
virtual const char* LineAt(int32 index) const;
|
||||||
|
virtual int32 LineLengthAt(int32 index) const;
|
||||||
|
|
||||||
virtual bool GetStatementLocationRange(
|
virtual bool GetStatementLocationRange(
|
||||||
const SourceLocation& location,
|
const SourceLocation& location,
|
||||||
|
|||||||
@@ -91,6 +91,13 @@ FileSourceCode::LineAt(int32 index) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
FileSourceCode::LineLengthAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fSourceFile->LineLengthAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
FileSourceCode::GetStatementLocationRange(const SourceLocation& location,
|
FileSourceCode::GetStatementLocationRange(const SourceLocation& location,
|
||||||
SourceLocation& _start, SourceLocation& _end) const
|
SourceLocation& _start, SourceLocation& _end) const
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
|
|
||||||
virtual int32 CountLines() const;
|
virtual int32 CountLines() const;
|
||||||
virtual const char* LineAt(int32 index) const;
|
virtual const char* LineAt(int32 index) const;
|
||||||
|
virtual int32 LineLengthAt(int32 index) const;
|
||||||
|
|
||||||
virtual bool GetStatementLocationRange(
|
virtual bool GetStatementLocationRange(
|
||||||
const SourceLocation& location,
|
const SourceLocation& location,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public:
|
|||||||
|
|
||||||
virtual int32 CountLines() const = 0;
|
virtual int32 CountLines() const = 0;
|
||||||
virtual const char* LineAt(int32 index) const = 0;
|
virtual const char* LineAt(int32 index) const = 0;
|
||||||
|
virtual int32 LineLengthAt(int32 index) const = 0;
|
||||||
|
|
||||||
virtual bool GetStatementLocationRange(
|
virtual bool GetStatementLocationRange(
|
||||||
const SourceLocation& location,
|
const SourceLocation& location,
|
||||||
|
|||||||
Reference in New Issue
Block a user