aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <nyamatongwe@gmail.com>2013-09-18 10:40:53 +1000
committernyamatongwe <nyamatongwe@gmail.com>2013-09-18 10:40:53 +1000
commit59b95105a1e71ad6b62a1970e88a0390850e5bfe (patch)
treeb2b837ef548ae7550d9e0bafb68ad50dcddd3f3c
parentc7eca832e818dbaa7180822fdea6f3aabcd83a32 (diff)
downloadscintilla-mirror-59b95105a1e71ad6b62a1970e88a0390850e5bfe.tar.gz
Reimplement notifications from ScintillaCocoa to ScintillaView as a delegate relationship
using ScintillaNotificationProtocol. Add optional command:idFrom: method to ScintillaNotificationProtocol for command notifications. In a future version registerNotifyCallback: and ScintillaCocoa::RegisterNotifyCallback will be deprecated.
-rw-r--r--cocoa/ScintillaCocoa.h4
-rw-r--r--cocoa/ScintillaCocoa.mm34
-rw-r--r--cocoa/ScintillaView.h7
-rw-r--r--cocoa/ScintillaView.mm140
-rw-r--r--doc/ScintillaDoc.html14
5 files changed, 119 insertions, 80 deletions
diff --git a/cocoa/ScintillaCocoa.h b/cocoa/ScintillaCocoa.h
index 4842e2098..c857fd21a 100644
--- a/cocoa/ScintillaCocoa.h
+++ b/cocoa/ScintillaCocoa.h
@@ -86,6 +86,9 @@ private:
TimerTarget* timerTarget;
NSEvent* lastMouseEvent;
+ id<ScintillaNotificationProtocol> delegate;
+ bool delegateHasCommand;
+
SciNotifyFunc notifyProc;
intptr_t notifyObj;
@@ -123,6 +126,7 @@ public:
ScintillaCocoa(InnerView* view, MarginView* viewMargin);
virtual ~ScintillaCocoa();
+ void SetDelegate(id<ScintillaNotificationProtocol> delegate_);
void RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback);
sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
diff --git a/cocoa/ScintillaCocoa.mm b/cocoa/ScintillaCocoa.mm
index 07f29bd8e..ce1042e9b 100644
--- a/cocoa/ScintillaCocoa.mm
+++ b/cocoa/ScintillaCocoa.mm
@@ -384,6 +384,8 @@ ScintillaCocoa::ScintillaCocoa(InnerView* view, MarginView* viewMargin)
wMargin = viewMargin;
timerTarget = [[TimerTarget alloc] init: this];
lastMouseEvent = NULL;
+ delegate = NULL;
+ delegateHasCommand = false;
notifyObj = NULL;
notifyProc = NULL;
capturedMouse = false;
@@ -1652,6 +1654,26 @@ void ScintillaCocoa::UpdateForScroll() {
//--------------------------------------------------------------------------------------------------
/**
+ * Register a delegate that will be called for notifications and commands.
+ * This provides similar functionality to RegisterNotifyCallback but in an
+ * Objective C way.
+ *
+ * @param delegate_ A pointer to an object that implements ScintillaNotificationProtocol.
+ */
+
+void ScintillaCocoa::SetDelegate(id<ScintillaNotificationProtocol> delegate_)
+{
+ delegate = delegate_;
+ delegateHasCommand = false;
+ if (delegate)
+ {
+ delegateHasCommand = [(id)delegate respondsToSelector: @selector(command:ctrlID:)];
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
* Used to register a callback function for a given window. This is used to emulate the way
* Windows notifies other controls (mainly up in the view hierarchy) about certain events.
*
@@ -1673,6 +1695,8 @@ void ScintillaCocoa::NotifyChange()
if (notifyProc != NULL)
notifyProc(notifyObj, WM_COMMAND, Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE),
(uintptr_t) this);
+ if (delegateHasCommand)
+ [delegate command:SCEN_CHANGE idFrom:GetCtrlID()];
}
//--------------------------------------------------------------------------------------------------
@@ -1682,6 +1706,8 @@ void ScintillaCocoa::NotifyFocus(bool focus)
if (notifyProc != NULL)
notifyProc(notifyObj, WM_COMMAND, Platform::LongFromTwoShorts(GetCtrlID(), (focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS)),
(uintptr_t) this);
+ if (delegateHasCommand)
+ [delegate command:(focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS) idFrom:GetCtrlID()];
}
//--------------------------------------------------------------------------------------------------
@@ -1694,12 +1720,12 @@ void ScintillaCocoa::NotifyFocus(bool focus)
*/
void ScintillaCocoa::NotifyParent(SCNotification scn)
{
+ scn.nmhdr.hwndFrom = (void*) this;
+ scn.nmhdr.idFrom = GetCtrlID();
if (notifyProc != NULL)
- {
- scn.nmhdr.hwndFrom = (void*) this;
- scn.nmhdr.idFrom = GetCtrlID();
notifyProc(notifyObj, WM_NOTIFY, GetCtrlID(), (uintptr_t) &scn);
- }
+ if (delegate)
+ [delegate notification:&scn];
}
//--------------------------------------------------------------------------------------------------
diff --git a/cocoa/ScintillaView.h b/cocoa/ScintillaView.h
index 02bdfac90..653f111d3 100644
--- a/cocoa/ScintillaView.h
+++ b/cocoa/ScintillaView.h
@@ -46,6 +46,8 @@ extern NSString *const SCIUpdateUINotification;
@protocol ScintillaNotificationProtocol
- (void)notification: (Scintilla::SCNotification*)notification;
+@optional
+- (void)command:(int)command idFrom:(int)idFrom;
@end
/**
@@ -92,7 +94,7 @@ extern NSString *const SCIUpdateUINotification;
@end
-@interface ScintillaView : NSView <InfoBarCommunicator>
+@interface ScintillaView : NSView <InfoBarCommunicator, ScintillaNotificationProtocol>
{
@private
// The back end is kind of a controller and model in one.
@@ -126,6 +128,8 @@ extern NSString *const SCIUpdateUINotification;
- (void) setCallback: (id <InfoBarCommunicator>) callback;
- (void) suspendDrawing: (BOOL) suspend;
+- (void) notification: (Scintilla::SCNotification*) notification;
+- (void) command:(int) command idFrom:(int) idFrom;
// Scroller handling
- (void) setMarginWidth: (int) width;
@@ -172,6 +176,7 @@ extern NSString *const SCIUpdateUINotification;
- (void) setLexerProperty: (NSString*) name value: (NSString*) value;
- (NSString*) getLexerProperty: (NSString*) name;
+// The delegate property should be used instead of registerNotifyCallback which will be deprecated.
- (void) registerNotifyCallback: (intptr_t) windowid value: (Scintilla::SciNotifyFunc) callback;
- (void) setInfoBar: (NSView <InfoBarCommunicator>*) aView top: (BOOL) top;
diff --git a/cocoa/ScintillaView.mm b/cocoa/ScintillaView.mm
index 9eae83718..ce0123982 100644
--- a/cocoa/ScintillaView.mm
+++ b/cocoa/ScintillaView.mm
@@ -956,93 +956,89 @@ static NSCursor *cursorFromEnum(Window::Cursor cursor)
//--------------------------------------------------------------------------------------------------
/**
- * Notification function used by Scintilla to call us back (e.g. for handling clicks on the
+ * Method receives notifications from Scintilla (e.g. for handling clicks on the
* folder margin or changes in the editor).
* A delegate can be set to receive all notifications. If set no handling takes place here, except
* for action pertaining to internal stuff (like the info bar).
*/
-static void notification(intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam)
+- (void) notification: (Scintilla::SCNotification*)scn
{
- // WM_NOTIFY means we got a parent notification with a special notification structure.
- // Here we don't really differentiate between parent and own notifications and handle both.
- ScintillaView* editor;
- switch (iMessage)
+ // Parent notification. Details are passed as SCNotification structure.
+
+ if (mDelegate != nil)
+ {
+ [mDelegate notification: scn];
+ if (scn->nmhdr.code != SCN_ZOOM && scn->nmhdr.code != SCN_UPDATEUI)
+ return;
+ }
+
+ switch (scn->nmhdr.code)
{
- case WM_NOTIFY:
+ case SCN_MARGINCLICK:
{
- // Parent notification. Details are passed as SCNotification structure.
- SCNotification* scn = reinterpret_cast<SCNotification*>(lParam);
- ScintillaCocoa *psc = reinterpret_cast<ScintillaCocoa*>(scn->nmhdr.hwndFrom);
- editor = reinterpret_cast<InnerView*>(psc->ContentView()).owner;
-
- if (editor.delegate != nil)
- {
- [editor.delegate notification: scn];
- if (scn->nmhdr.code != SCN_ZOOM && scn->nmhdr.code != SCN_UPDATEUI)
- return;
- }
-
- switch (scn->nmhdr.code)
+ if (scn->margin == 2)
{
- case SCN_MARGINCLICK:
- {
- if (scn->margin == 2)
- {
- // Click on the folder margin. Toggle the current line if possible.
- long line = [editor getGeneralProperty: SCI_LINEFROMPOSITION parameter: scn->position];
- [editor setGeneralProperty: SCI_TOGGLEFOLD value: line];
- }
- break;
- };
- case SCN_MODIFIED:
- {
- // Decide depending on the modification type what to do.
- // There can be more than one modification carried by one notification.
- if (scn->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT))
- [editor sendNotification: NSTextDidChangeNotification];
- break;
- }
- case SCN_ZOOM:
- {
- // A zoom change happened. Notify info bar if there is one.
- float zoom = [editor getGeneralProperty: SCI_GETZOOM parameter: 0];
- long fontSize = [editor getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT];
- float factor = (zoom / fontSize) + 1;
- [editor->mInfoBar notify: IBNZoomChanged message: nil location: NSZeroPoint value: factor];
- break;
- }
- case SCN_UPDATEUI:
- {
- // Triggered whenever changes in the UI state need to be reflected.
- // These can be: caret changes, selection changes etc.
- NSPoint caretPosition = editor->mBackend->GetCaretPosition();
- [editor->mInfoBar notify: IBNCaretChanged message: nil location: caretPosition value: 0];
- [editor sendNotification: SCIUpdateUINotification];
- if (scn->updated & (SC_UPDATE_SELECTION | SC_UPDATE_CONTENT))
- {
- [editor sendNotification: NSTextViewDidChangeSelectionNotification];
- }
- break;
- }
+ // Click on the folder margin. Toggle the current line if possible.
+ long line = [self getGeneralProperty: SCI_LINEFROMPOSITION parameter: scn->position];
+ [self setGeneralProperty: SCI_TOGGLEFOLD value: line];
}
break;
+ };
+ case SCN_MODIFIED:
+ {
+ // Decide depending on the modification type what to do.
+ // There can be more than one modification carried by one notification.
+ if (scn->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT))
+ [self sendNotification: NSTextDidChangeNotification];
+ break;
+ }
+ case SCN_ZOOM:
+ {
+ // A zoom change happened. Notify info bar if there is one.
+ float zoom = [self getGeneralProperty: SCI_GETZOOM parameter: 0];
+ long fontSize = [self getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT];
+ float factor = (zoom / fontSize) + 1;
+ [mInfoBar notify: IBNZoomChanged message: nil location: NSZeroPoint value: factor];
+ break;
}
- case WM_COMMAND:
+ case SCN_UPDATEUI:
{
- // Notifications for the editor itself.
- ScintillaCocoa* backend = reinterpret_cast<ScintillaCocoa*>(lParam);
- editor = backend->TopContainer();
- switch (wParam >> 16)
+ // Triggered whenever changes in the UI state need to be reflected.
+ // These can be: caret changes, selection changes etc.
+ NSPoint caretPosition = mBackend->GetCaretPosition();
+ [mInfoBar notify: IBNCaretChanged message: nil location: caretPosition value: 0];
+ [self sendNotification: SCIUpdateUINotification];
+ if (scn->updated & (SC_UPDATE_SELECTION | SC_UPDATE_CONTENT))
{
- case SCEN_KILLFOCUS:
- [editor sendNotification: NSTextDidEndEditingNotification];
- break;
- case SCEN_SETFOCUS: // Nothing to do for now.
- break;
+ [self sendNotification: NSTextViewDidChangeSelectionNotification];
}
break;
}
- };
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Method receives notifications from Scintilla for gaining and losing focus and for changes.
+ * A delegate can be set to receive all notifications.
+ */
+- (void) command:(int)command idFrom:(int)idFrom
+{
+ if ((mDelegate != nil) && ([(id)mDelegate respondsToSelector:@selector(command:ctrlID:)]))
+ {
+ [mDelegate command:command idFrom:idFrom];
+ }
+
+ // Notifications for the editor itself.
+ switch (command)
+ {
+ case SCEN_KILLFOCUS:
+ [self sendNotification: NSTextDidEndEditingNotification];
+ break;
+ case SCEN_SETFOCUS: // Nothing to do for now.
+ break;
+ }
}
//--------------------------------------------------------------------------------------------------
@@ -1084,7 +1080,7 @@ static void notification(intptr_t windowid, unsigned int iMessage, uintptr_t wPa
// Establish a connection from the back end to this container so we can handle situations
// which require our attention.
- mBackend->RegisterNotifyCallback(nil, notification);
+ mBackend->SetDelegate(self);
// Setup a special indicator used in the editor to provide visual feedback for
// input composition, depending on language, keyboard etc.
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 137338146..272b0f4e0 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -82,7 +82,7 @@
<h1>Scintilla Documentation</h1>
- <p>Last edited 7 September 2013 NH</p>
+ <p>Last edited 18 September 2013 NH</p>
<p>There is <a class="jump" href="Design.html">an overview of the internal design of
Scintilla</a>.<br />
@@ -6437,7 +6437,12 @@ implemented and thus which methods may be called.</p>
<p>Notifications are sent (fired) from the Scintilla control to its container when an event has
occurred that may interest the container. Notifications are sent using the
- <code>WM_NOTIFY</code> message on Windows and the "notify" signal on GTK+. The container is
+ <code>WM_NOTIFY</code> message on Windows and the "notify" signal on GTK+.
+ On Cocoa, a delegate implementing the <code>ScintillaNotificationProtocol</code>
+ may be set to receive notifications or the <code>ScintillaView</code> class may be subclassed and the
+ <code>notification:</code> method overridden. Overriding <code>notification:</code> allows the
+ subclass to control whether default handling is performed.
+ The container is
passed a <code>SCNotification</code> structure containing information about the event.</p>
<pre id="SCNotification">
struct NotifyHeader { // This matches the Win32 NMHDR structure
@@ -6523,7 +6528,10 @@ struct SCNotification {
</code>
<p>The following additional notifications are sent using the <code>WM_COMMAND</code> message on
- Windows and the "Command" signal on GTK+. This emulates the Windows Edit control. Only the lower
+ Windows and the "Command" signal on GTK+.
+ On Cocoa, a delegate implementing the
+ <code>ScintillaNotificationProtocol</code> with a <code>command:idFrom:</code> method may be set.
+ This emulates the Windows Edit control. Only the lower
16 bits of the control's ID is passed in these notifications.</p>
<code><a class="message" href="#SCEN_CHANGE">SCEN_CHANGE</a><br />
<a class="message" href="#SCEN_SETFOCUS">SCEN_SETFOCUS</a><br />