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