Now maintains the "Paste" menu item - it is enabled/disabled when there
is data available in the clipboard or not. "Copy" and "Select All" now work. All position updates are now handled by a separate looper class (UpdateLooper), and are actually applied at the editor. UpdateLooper will send a kMsgUpdateData to its target synchronously when necessary. Seeking a file now works nicely and very smooth. HeaderView::MessageReceived() and UpdateLooper::MessageReceived() only consider the most current update message for kMsgSliderUpdate resp. kMsgPositionUpdate. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6707 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -11,6 +11,9 @@
|
||||
// for SetLimits()
|
||||
|
||||
#include <Window.h>
|
||||
#include <Clipboard.h>
|
||||
#include <Autolock.h>
|
||||
#include <MessageQueue.h>
|
||||
#include <TextControl.h>
|
||||
#include <StringView.h>
|
||||
#include <Slider.h>
|
||||
@@ -123,6 +126,19 @@ class HeaderView : public BView, public BInvoker {
|
||||
};
|
||||
|
||||
|
||||
class UpdateLooper : public BLooper {
|
||||
public:
|
||||
UpdateLooper(const char *name, DataEditor &editor, BMessenger messenger);
|
||||
virtual ~UpdateLooper();
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
|
||||
private:
|
||||
DataEditor &fEditor;
|
||||
BMessenger fMessenger;
|
||||
};
|
||||
|
||||
|
||||
//----------------------
|
||||
|
||||
|
||||
@@ -563,6 +579,16 @@ HeaderView::MessageReceived(BMessage *message)
|
||||
|
||||
case kMsgSliderUpdate:
|
||||
{
|
||||
// First, make sure we're only considering the most
|
||||
// up-to-date message in the queue (which might not
|
||||
// be this one).
|
||||
// If there is another message of this type in the
|
||||
// queue, we're just ignoring the current message.
|
||||
|
||||
if (Looper()->MessageQueue()->FindMessage(kMsgSliderUpdate, 0) != NULL)
|
||||
break;
|
||||
|
||||
// if nothing has changed, we can ignore this message as well
|
||||
if (fPosition == fPositionSlider->Position())
|
||||
break;
|
||||
|
||||
@@ -629,6 +655,83 @@ HeaderView::MessageReceived(BMessage *message)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
/** The purpose of this looper is to off-load the editor data
|
||||
* loading from the main window looper.
|
||||
* It will listen to the offset changes of the editor, let
|
||||
* him update its data, and will then synchronously notify
|
||||
* the target.
|
||||
* That way, simple offset changes will not stop the main
|
||||
* looper from operating. Therefore, all offset updates
|
||||
* for the editor will go through this looper.
|
||||
*/
|
||||
|
||||
UpdateLooper::UpdateLooper(const char *name, DataEditor &editor, BMessenger target)
|
||||
: BLooper(name),
|
||||
fEditor(editor),
|
||||
fMessenger(target)
|
||||
{
|
||||
fEditor.StartWatching(this);
|
||||
}
|
||||
|
||||
|
||||
UpdateLooper::~UpdateLooper()
|
||||
{
|
||||
fEditor.StopWatching(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UpdateLooper::MessageReceived(BMessage *message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgPositionUpdate:
|
||||
{
|
||||
// First, make sure we're only considering the most
|
||||
// up-to-date message in the queue (which might not
|
||||
// be this one).
|
||||
// If there is another message of this type in the
|
||||
// queue, we're just ignoring the current message.
|
||||
|
||||
if (Looper()->MessageQueue()->FindMessage(kMsgPositionUpdate, 0) != NULL)
|
||||
break;
|
||||
|
||||
off_t position;
|
||||
if (message->FindInt64("position", &position) == B_OK) {
|
||||
BAutolock locker(fEditor);
|
||||
fEditor.SetViewOffset(position);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgDataEditorOffsetChange:
|
||||
{
|
||||
bool updated = false;
|
||||
|
||||
if (fEditor.Lock()) {
|
||||
fEditor.UpdateIfNeeded(&updated);
|
||||
fEditor.Unlock();
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
BMessage reply;
|
||||
fMessenger.SendMessage(kMsgUpdateData, &reply);
|
||||
// We are doing a synchronously transfer, to prevent
|
||||
// that we're already locking the editor again when
|
||||
// our target wants to get the editor data.
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BLooper::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
ProbeView::ProbeView(BRect rect, entry_ref *ref, const char *attribute)
|
||||
: BView(rect, "probeView", B_FOLLOW_ALL, B_WILL_DRAW)
|
||||
{
|
||||
@@ -674,7 +777,14 @@ ProbeView::UpdateSizeLimits()
|
||||
void
|
||||
ProbeView::DetachedFromWindow()
|
||||
{
|
||||
if (fUpdateLooper->Lock())
|
||||
fUpdateLooper->Quit();
|
||||
fUpdateLooper = NULL;
|
||||
|
||||
fEditor.StopWatching(this);
|
||||
fDataView->StopWatching(fHeaderView, kDataViewCursorPosition);
|
||||
fDataView->StopWatching(this, kDataViewSelection);
|
||||
be_clipboard->StopWatching(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -692,8 +802,13 @@ ProbeView::AddFileMenuItems(BMenu *menu, int32 index)
|
||||
void
|
||||
ProbeView::AttachedToWindow()
|
||||
{
|
||||
fUpdateLooper = new UpdateLooper(fEditor.Ref().name, fEditor, BMessenger(fDataView));
|
||||
fUpdateLooper->Run();
|
||||
|
||||
fEditor.StartWatching(this);
|
||||
fDataView->StartWatching(fHeaderView, kDataViewCursorPosition);
|
||||
fDataView->StartWatching(this, kDataViewSelection);
|
||||
be_clipboard->StartWatching(this);
|
||||
|
||||
// Add menu to window
|
||||
|
||||
@@ -719,9 +834,13 @@ ProbeView::AttachedToWindow()
|
||||
menu->AddItem(new BMenuItem("Undo", NULL, 'Z', B_COMMAND_KEY));
|
||||
menu->AddItem(new BMenuItem("Redo", NULL, 'Z', B_COMMAND_KEY | B_SHIFT_KEY));
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(new BMenuItem("Copy", NULL, 'C', B_COMMAND_KEY));
|
||||
menu->AddItem(new BMenuItem("Paste", NULL, 'V', B_COMMAND_KEY));
|
||||
menu->AddItem(new BMenuItem("Select All", NULL, 'A', B_COMMAND_KEY));
|
||||
menu->AddItem(item = new BMenuItem("Copy", new BMessage(B_COPY), 'C', B_COMMAND_KEY));
|
||||
item->SetTarget(fDataView);
|
||||
menu->AddItem(fPasteMenuItem = new BMenuItem("Paste", new BMessage(B_PASTE), 'V', B_COMMAND_KEY));
|
||||
fPasteMenuItem->SetTarget(fDataView);
|
||||
CheckClipboard();
|
||||
menu->AddItem(item = new BMenuItem("Select All", new BMessage(B_SELECT_ALL), 'A', B_COMMAND_KEY));
|
||||
item->SetTarget(fDataView);
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(new BMenuItem("Find" B_UTF8_ELLIPSIS, NULL, 'F', B_COMMAND_KEY));
|
||||
menu->AddItem(new BMenuItem("Find Again", NULL, 'G', B_COMMAND_KEY));
|
||||
@@ -799,7 +918,7 @@ ProbeView::AttachedToWindow()
|
||||
void
|
||||
ProbeView::AllAttached()
|
||||
{
|
||||
fHeaderView->SetTarget(this);
|
||||
fHeaderView->SetTarget(fUpdateLooper);
|
||||
}
|
||||
|
||||
|
||||
@@ -811,6 +930,28 @@ ProbeView::WindowActivated(bool active)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ProbeView::CheckClipboard()
|
||||
{
|
||||
if (!be_clipboard->Lock())
|
||||
return;
|
||||
|
||||
bool hasData = false;
|
||||
BMessage *clip;
|
||||
if ((clip = be_clipboard->Data()) != NULL) {
|
||||
const void *data;
|
||||
ssize_t size;
|
||||
if (clip->FindData(B_FILE_MIME_TYPE, B_MIME_TYPE, &data, &size) == B_OK
|
||||
|| clip->FindData("text/plain", B_MIME_TYPE, &data, &size) == B_OK)
|
||||
hasData = true;
|
||||
}
|
||||
|
||||
be_clipboard->Unlock();
|
||||
|
||||
fPasteMenuItem->SetEnabled(hasData);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ProbeView::MessageReceived(BMessage *message)
|
||||
{
|
||||
@@ -826,8 +967,8 @@ ProbeView::MessageReceived(BMessage *message)
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgPositionUpdate:
|
||||
// ToDo: update data
|
||||
case B_CLIPBOARD_CHANGED:
|
||||
CheckClipboard();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
|
||||
|
||||
class BScrollView;
|
||||
class BMenuItem;
|
||||
|
||||
class HeaderView;
|
||||
class DataView;
|
||||
class UpdateLooper;
|
||||
|
||||
|
||||
class ProbeView : public BView {
|
||||
@@ -35,10 +37,14 @@ class ProbeView : public BView {
|
||||
void UpdateSizeLimits();
|
||||
|
||||
private:
|
||||
void CheckClipboard();
|
||||
|
||||
DataEditor fEditor;
|
||||
UpdateLooper *fUpdateLooper;
|
||||
HeaderView *fHeaderView;
|
||||
DataView *fDataView;
|
||||
BScrollView *fScrollView;
|
||||
BMenuItem *fPasteMenuItem;
|
||||
};
|
||||
|
||||
#endif /* PROBE_VIEW_H */
|
||||
|
||||
Reference in New Issue
Block a user