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:
Axel Dörfler 2004-02-18 14:37:09 +00:00
parent d556aa00c8
commit 602992140d
3 changed files with 182 additions and 8 deletions

View File

@ -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 */

View File

@ -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)
{

View File

@ -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);