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()
|
// for SetLimits()
|
||||||
|
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
#include <Clipboard.h>
|
||||||
|
#include <Autolock.h>
|
||||||
|
#include <MessageQueue.h>
|
||||||
#include <TextControl.h>
|
#include <TextControl.h>
|
||||||
#include <StringView.h>
|
#include <StringView.h>
|
||||||
#include <Slider.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:
|
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())
|
if (fPosition == fPositionSlider->Position())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -629,6 +655,83 @@ HeaderView::MessageReceived(BMessage *message)
|
|||||||
// #pragma mark -
|
// #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)
|
ProbeView::ProbeView(BRect rect, entry_ref *ref, const char *attribute)
|
||||||
: BView(rect, "probeView", B_FOLLOW_ALL, B_WILL_DRAW)
|
: BView(rect, "probeView", B_FOLLOW_ALL, B_WILL_DRAW)
|
||||||
{
|
{
|
||||||
@@ -674,7 +777,14 @@ ProbeView::UpdateSizeLimits()
|
|||||||
void
|
void
|
||||||
ProbeView::DetachedFromWindow()
|
ProbeView::DetachedFromWindow()
|
||||||
{
|
{
|
||||||
|
if (fUpdateLooper->Lock())
|
||||||
|
fUpdateLooper->Quit();
|
||||||
|
fUpdateLooper = NULL;
|
||||||
|
|
||||||
fEditor.StopWatching(this);
|
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
|
void
|
||||||
ProbeView::AttachedToWindow()
|
ProbeView::AttachedToWindow()
|
||||||
{
|
{
|
||||||
|
fUpdateLooper = new UpdateLooper(fEditor.Ref().name, fEditor, BMessenger(fDataView));
|
||||||
|
fUpdateLooper->Run();
|
||||||
|
|
||||||
fEditor.StartWatching(this);
|
fEditor.StartWatching(this);
|
||||||
fDataView->StartWatching(fHeaderView, kDataViewCursorPosition);
|
fDataView->StartWatching(fHeaderView, kDataViewCursorPosition);
|
||||||
|
fDataView->StartWatching(this, kDataViewSelection);
|
||||||
|
be_clipboard->StartWatching(this);
|
||||||
|
|
||||||
// Add menu to window
|
// Add menu to window
|
||||||
|
|
||||||
@@ -719,9 +834,13 @@ ProbeView::AttachedToWindow()
|
|||||||
menu->AddItem(new BMenuItem("Undo", NULL, 'Z', B_COMMAND_KEY));
|
menu->AddItem(new BMenuItem("Undo", NULL, 'Z', B_COMMAND_KEY));
|
||||||
menu->AddItem(new BMenuItem("Redo", NULL, 'Z', B_COMMAND_KEY | B_SHIFT_KEY));
|
menu->AddItem(new BMenuItem("Redo", NULL, 'Z', B_COMMAND_KEY | B_SHIFT_KEY));
|
||||||
menu->AddSeparatorItem();
|
menu->AddSeparatorItem();
|
||||||
menu->AddItem(new BMenuItem("Copy", NULL, 'C', B_COMMAND_KEY));
|
menu->AddItem(item = new BMenuItem("Copy", new BMessage(B_COPY), 'C', B_COMMAND_KEY));
|
||||||
menu->AddItem(new BMenuItem("Paste", NULL, 'V', B_COMMAND_KEY));
|
item->SetTarget(fDataView);
|
||||||
menu->AddItem(new BMenuItem("Select All", NULL, 'A', B_COMMAND_KEY));
|
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->AddSeparatorItem();
|
||||||
menu->AddItem(new BMenuItem("Find" B_UTF8_ELLIPSIS, NULL, 'F', B_COMMAND_KEY));
|
menu->AddItem(new BMenuItem("Find" B_UTF8_ELLIPSIS, NULL, 'F', B_COMMAND_KEY));
|
||||||
menu->AddItem(new BMenuItem("Find Again", NULL, 'G', B_COMMAND_KEY));
|
menu->AddItem(new BMenuItem("Find Again", NULL, 'G', B_COMMAND_KEY));
|
||||||
@@ -799,7 +918,7 @@ ProbeView::AttachedToWindow()
|
|||||||
void
|
void
|
||||||
ProbeView::AllAttached()
|
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
|
void
|
||||||
ProbeView::MessageReceived(BMessage *message)
|
ProbeView::MessageReceived(BMessage *message)
|
||||||
{
|
{
|
||||||
@@ -826,8 +967,8 @@ ProbeView::MessageReceived(BMessage *message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case kMsgPositionUpdate:
|
case B_CLIPBOARD_CHANGED:
|
||||||
// ToDo: update data
|
CheckClipboard();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -14,9 +14,11 @@
|
|||||||
|
|
||||||
|
|
||||||
class BScrollView;
|
class BScrollView;
|
||||||
|
class BMenuItem;
|
||||||
|
|
||||||
class HeaderView;
|
class HeaderView;
|
||||||
class DataView;
|
class DataView;
|
||||||
|
class UpdateLooper;
|
||||||
|
|
||||||
|
|
||||||
class ProbeView : public BView {
|
class ProbeView : public BView {
|
||||||
@@ -35,10 +37,14 @@ class ProbeView : public BView {
|
|||||||
void UpdateSizeLimits();
|
void UpdateSizeLimits();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void CheckClipboard();
|
||||||
|
|
||||||
DataEditor fEditor;
|
DataEditor fEditor;
|
||||||
|
UpdateLooper *fUpdateLooper;
|
||||||
HeaderView *fHeaderView;
|
HeaderView *fHeaderView;
|
||||||
DataView *fDataView;
|
DataView *fDataView;
|
||||||
BScrollView *fScrollView;
|
BScrollView *fScrollView;
|
||||||
|
BMenuItem *fPasteMenuItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PROBE_VIEW_H */
|
#endif /* PROBE_VIEW_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user