Implemented proper focus handling in DataView instead of forcing focus
whenever the window got activated. New DataView::MakeVisible() makes sure the specified position is visible in the view, and scrolls to it if not (both, horizontally and vertically). Implemented cursor navigation and selection extension in the DataView class. Fixed a bug in DataView::SetSelection() that could let slip through invalid values. Renamed DataEditor observer notices. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6634 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d556aa00c8
commit
602992140d
@ -96,7 +96,7 @@ class DataEditor : public BLocker {
|
||||
size_t fBlockSize;
|
||||
};
|
||||
|
||||
static const uint32 kMsgDataEditorStateChange = 'deSC';
|
||||
static const uint32 kMsgDataEditorUpdate = 'deUp';
|
||||
static const uint32 kDataEditorStateChange = 'deSC';
|
||||
static const uint32 kDataEditorUpdate = 'deUp';
|
||||
|
||||
#endif /* DATA_EDITOR_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "DataView.h"
|
||||
#include "DataEditor.h"
|
||||
|
||||
#include <Looper.h>
|
||||
#include <Window.h>
|
||||
#include <ScrollBar.h>
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ DataView::MessageReceived(BMessage *message)
|
||||
break;
|
||||
|
||||
switch (what) {
|
||||
case kMsgDataEditorUpdate:
|
||||
case kDataEditorUpdate:
|
||||
UpdateFromEditor(message);
|
||||
break;
|
||||
}
|
||||
@ -387,7 +387,7 @@ DataView::DrawSelectionBlock(view_focus which)
|
||||
void
|
||||
DataView::DrawSelection()
|
||||
{
|
||||
if (fIsActive) {
|
||||
if (IsFocus() && fIsActive) {
|
||||
DrawSelectionBlock(fFocus);
|
||||
DrawSelectionFrame(fFocus == kHexFocus ? kAsciiFocus : kHexFocus);
|
||||
} else {
|
||||
@ -400,6 +400,8 @@ DataView::DrawSelection()
|
||||
void
|
||||
DataView::SetSelection(int32 start, int32 end, view_focus focus)
|
||||
{
|
||||
// correct the values if necessary
|
||||
|
||||
if (start > end) {
|
||||
int32 temp = start;
|
||||
start = end;
|
||||
@ -408,8 +410,13 @@ DataView::SetSelection(int32 start, int32 end, view_focus focus)
|
||||
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
else if (start > (int32)fDataSize - 1)
|
||||
start = (int32)fDataSize - 1;
|
||||
|
||||
if (end > (int32)fDataSize - 1)
|
||||
end = (int32)fDataSize - 1;
|
||||
else if (end < 0)
|
||||
end = 0;
|
||||
|
||||
if (fStart == start && fEnd == end) {
|
||||
// nothing has changed, no need to update
|
||||
@ -471,6 +478,47 @@ DataView::InvalidateRange(int32 start, int32 end)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataView::MakeVisible(int32 position)
|
||||
{
|
||||
if (position < 0 || position > int32(fDataSize) - 1)
|
||||
return;
|
||||
|
||||
BRect frame = SelectionFrame(fFocus, position, position);
|
||||
BRect bounds = Bounds();
|
||||
if (bounds.Contains(frame))
|
||||
return;
|
||||
|
||||
// special case the first and the last line and column, so that
|
||||
// we can take kHorizontalSpace & kVerticalSpace into account
|
||||
|
||||
if ((position % kBlockSize) == 0)
|
||||
frame.left -= kHorizontalSpace;
|
||||
else if ((position % kBlockSize) == kBlockSize - 1)
|
||||
frame.right += kHorizontalSpace;
|
||||
|
||||
if (position < int32(kBlockSize))
|
||||
frame.top -= kVerticalSpace;
|
||||
else if (position > int32(fDataSize - kBlockSize))
|
||||
frame.bottom += kVerticalSpace;
|
||||
|
||||
// compute the scroll point
|
||||
|
||||
BPoint point = bounds.LeftTop();
|
||||
if (bounds.left > frame.left)
|
||||
point.x = frame.left;
|
||||
else if (bounds.right < frame.right)
|
||||
point.x = frame.right - bounds.Width();
|
||||
|
||||
if (bounds.top > frame.top)
|
||||
point.y = frame.top;
|
||||
else if (bounds.bottom < frame.bottom)
|
||||
point.y = frame.bottom - bounds.Height();
|
||||
|
||||
ScrollTo(point);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataView::SetBase(base_type type)
|
||||
{
|
||||
@ -494,14 +542,17 @@ DataView::SetFocus(view_focus which)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataView::WindowActivated(bool active)
|
||||
void
|
||||
DataView::SetActive(bool active)
|
||||
{
|
||||
if (active == fIsActive)
|
||||
return;
|
||||
|
||||
fIsActive = active;
|
||||
|
||||
// only redraw the focussed part
|
||||
|
||||
if (fIsActive) {
|
||||
if (IsFocus() && active) {
|
||||
DrawSelectionFrame(fFocus);
|
||||
DrawSelectionBlock(fFocus);
|
||||
} else {
|
||||
@ -511,6 +562,30 @@ DataView::WindowActivated(bool active)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataView::WindowActivated(bool active)
|
||||
{
|
||||
BView::WindowActivated(active);
|
||||
SetActive(active);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataView::MakeFocus(bool focus)
|
||||
{
|
||||
bool previous = IsFocus();
|
||||
BView::MakeFocus(focus);
|
||||
|
||||
if (focus == previous)
|
||||
return;
|
||||
|
||||
if (Window()->IsActive() && focus)
|
||||
SetActive(true);
|
||||
else if (!Window()->IsActive() || !focus)
|
||||
SetActive(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataView::UpdateScroller()
|
||||
{
|
||||
@ -549,6 +624,8 @@ DataView::FrameResized(float width, float height)
|
||||
void
|
||||
DataView::MouseDown(BPoint where)
|
||||
{
|
||||
MakeFocus(true);
|
||||
|
||||
BMessage *message = Looper()->CurrentMessage();
|
||||
int32 buttons;
|
||||
if (message == NULL || message->FindInt32("buttons", &buttons) != B_OK
|
||||
@ -596,6 +673,98 @@ DataView::MouseUp(BPoint where)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataView::KeyDown(const char *bytes, int32 numBytes)
|
||||
{
|
||||
int32 modifiers;
|
||||
if (Looper()->CurrentMessage() == NULL
|
||||
|| Looper()->CurrentMessage()->FindInt32("modifiers", &modifiers) != B_OK)
|
||||
modifiers = ::modifiers();
|
||||
|
||||
switch (bytes[0]) {
|
||||
case B_LEFT_ARROW:
|
||||
SetSelection(fStart - 1, modifiers & B_SHIFT_KEY ? fEnd : fStart - 1);
|
||||
MakeVisible(fStart);
|
||||
break;
|
||||
case B_RIGHT_ARROW:
|
||||
SetSelection(modifiers & B_SHIFT_KEY ? fStart : fEnd + 1, fEnd + 1);
|
||||
MakeVisible(fEnd);
|
||||
break;
|
||||
case B_UP_ARROW:
|
||||
{
|
||||
int32 start = fStart - int32(kBlockSize);
|
||||
if (start < 0) {
|
||||
if (modifiers & B_SHIFT_KEY)
|
||||
start = 0;
|
||||
else
|
||||
start = fStart;
|
||||
}
|
||||
|
||||
SetSelection(start, modifiers & B_SHIFT_KEY ? fEnd : start);
|
||||
MakeVisible(fStart);
|
||||
break;
|
||||
}
|
||||
case B_DOWN_ARROW:
|
||||
{
|
||||
int32 end = fEnd + int32(kBlockSize);
|
||||
if (end >= int32(fDataSize)) {
|
||||
if (modifiers & B_SHIFT_KEY)
|
||||
end = int32(fDataSize) - 1;
|
||||
else
|
||||
end = fEnd;
|
||||
}
|
||||
|
||||
SetSelection(modifiers & B_SHIFT_KEY ? fStart : end, end);
|
||||
MakeVisible(fEnd);
|
||||
break;
|
||||
}
|
||||
|
||||
case B_PAGE_UP:
|
||||
{
|
||||
// scroll one page up, but keep the same cursor column
|
||||
|
||||
BRect frame = SelectionFrame(fFocus, fStart, fStart);
|
||||
frame.OffsetBy(0, -Bounds().Height());
|
||||
if (frame.top <= kVerticalSpace)
|
||||
frame.top = kVerticalSpace + 1;
|
||||
ScrollBy(0, -Bounds().Height());
|
||||
|
||||
int32 position = PositionAt(fFocus, frame.LeftTop());
|
||||
SetSelection(position, position);
|
||||
break;
|
||||
}
|
||||
case B_PAGE_DOWN:
|
||||
{
|
||||
// scroll one page down, but keep the same cursor column
|
||||
|
||||
BRect frame = SelectionFrame(fFocus, fStart, fStart);
|
||||
frame.OffsetBy(0, Bounds().Height());
|
||||
|
||||
float lastLine = fFontHeight * ((fDataSize - 1) / kBlockSize) + kVerticalSpace;
|
||||
if (frame.top > lastLine)
|
||||
frame.top = lastLine;
|
||||
ScrollBy(0, Bounds().Height());
|
||||
|
||||
int32 position = PositionAt(fFocus, frame.LeftTop());
|
||||
SetSelection(position, position);
|
||||
break;
|
||||
}
|
||||
case B_HOME:
|
||||
SetSelection(0, 0);
|
||||
MakeVisible(fStart);
|
||||
break;
|
||||
case B_END:
|
||||
SetSelection(fDataSize - 1, fDataSize - 1);
|
||||
MakeVisible(fStart);
|
||||
break;
|
||||
case B_TAB:
|
||||
SetFocus(fFocus == kHexFocus ? kAsciiFocus : kHexFocus);
|
||||
MakeVisible(fStart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DataView::SetFont(const BFont *font, uint32 properties)
|
||||
{
|
||||
|
@ -41,7 +41,10 @@ class DataView : public BView {
|
||||
virtual void MouseMoved(BPoint where, uint32 transit, const BMessage *message);
|
||||
virtual void MouseUp(BPoint where);
|
||||
|
||||
virtual void KeyDown(const char *bytes, int32 numBytes);
|
||||
|
||||
virtual void WindowActivated(bool active);
|
||||
virtual void MakeFocus(bool focus);
|
||||
virtual void FrameResized(float width, float height);
|
||||
virtual void SetFont(const BFont *font, uint32 properties = B_FONT_ALL);
|
||||
virtual void GetPreferredSize(float *_width, float *_height);
|
||||
@ -49,6 +52,7 @@ class DataView : public BView {
|
||||
void SetFontSize(float point);
|
||||
void UpdateScroller();
|
||||
|
||||
void MakeVisible(int32 position);
|
||||
void SetSelection(int32 start, int32 end, view_focus focus = kNoFocus);
|
||||
void GetSelection(int32 &start, int32 &end);
|
||||
void InvalidateRange(int32 start, int32 end);
|
||||
@ -63,6 +67,7 @@ class DataView : public BView {
|
||||
void DrawSelectionFrame(view_focus which);
|
||||
void DrawSelectionBlock(view_focus which);
|
||||
void DrawSelection();
|
||||
void SetActive(bool active);
|
||||
void SetFocus(view_focus which);
|
||||
|
||||
void UpdateFromEditor(BMessage *message = NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user