From 602992140d69561077b9fafbdc49272fa30cdf41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 18 Feb 2004 14:37:09 +0000 Subject: [PATCH] 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 --- src/apps/diskprobe/DataEditor.h | 4 +- src/apps/diskprobe/DataView.cpp | 181 ++++++++++++++++++++++++++++++-- src/apps/diskprobe/DataView.h | 5 + 3 files changed, 182 insertions(+), 8 deletions(-) diff --git a/src/apps/diskprobe/DataEditor.h b/src/apps/diskprobe/DataEditor.h index 027eba4b51..07a7cc794e 100644 --- a/src/apps/diskprobe/DataEditor.h +++ b/src/apps/diskprobe/DataEditor.h @@ -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 */ diff --git a/src/apps/diskprobe/DataView.cpp b/src/apps/diskprobe/DataView.cpp index 030892ac22..8a34e859b9 100644 --- a/src/apps/diskprobe/DataView.cpp +++ b/src/apps/diskprobe/DataView.cpp @@ -7,7 +7,7 @@ #include "DataView.h" #include "DataEditor.h" -#include +#include #include @@ -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) { diff --git a/src/apps/diskprobe/DataView.h b/src/apps/diskprobe/DataView.h index 4c528e86f5..d23ac0358f 100644 --- a/src/apps/diskprobe/DataView.h +++ b/src/apps/diskprobe/DataView.h @@ -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);