diff mde/content/ServiceContent.d @ 170:e45226d3deae

Context menu services not applicable to the current type can now be hidden. Added files missing from previous commits.
author Diggory Hardy <diggory.hardy@gmail.com>
date Mon, 29 Jun 2009 21:20:16 +0200
parents mde/content/Services.d@1125ba603af6
children 7f7b2011b759
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mde/content/ServiceContent.d	Mon Jun 29 21:20:16 2009 +0200
@@ -0,0 +1,140 @@
+/* LICENSE BLOCK
+Part of mde: a Modular D game-oriented Engine
+Copyright © 2007-2009 Diggory Hardy
+
+This program is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation, either
+version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+/** Content services.
+ *
+ * Each is a Content, so it can be used in a menu. Since the content being
+ * acted on is not passed when functions are called like this, it is set when
+ * a context menu is opened, which also allows the services to specify their
+ * compatibility with the content (type) passed (via BoolContent value and
+ * callbacks).
+ */
+module mde.content.ServiceContent;
+
+import mde.content.AStringContent;
+
+/** Interface for ServiceContent and ServiceContentList. */
+interface IServiceContent {
+    void setContent (Content cont);
+}
+
+/** A class for services acting on content.
+ *
+ * Provides services for any content usable as type T, where T is some content
+ * type.
+ * 
+ * The (boolean) value is true to indicate this service can act on the passed
+ * content type, false if not. */
+class ServiceContent(T : Content = AStringContent) : Content, IServiceContent, IBoolContent, IEventContent {
+    this (char[] symbol) {
+	super (symbol);
+    }
+    
+    /** Pass the content this service should prepare for.
+     *
+     * Stores the reference, because it won't be passed later. */
+    override void setContent (Content cont) {
+	activeCont = cast(T)cont;
+    }
+    
+    override bool opCall () {
+	return activeCont is null;
+    }
+    // Doesn't support directly setting the value
+    override void opAssign (bool val) {}
+    
+package:
+    T activeCont;
+}
+
+/** Aliases for common types */
+alias ServiceContent!(AStringContent) AStringService;
+alias ServiceContent!(IntContent) IntService;	///ditto
+
+/** A generic way to handle a list of type IContent. */
+class ServiceContentList : ContentList, IServiceContent, IBoolContent
+{
+    this (char[] symbol) {
+	super (symbol);
+    }
+    
+    void setContent (Content cont) {
+	foreach (child; list_) {
+	    debug assert (cast(IServiceContent)child !is null);
+	    (cast(IServiceContent)child).setContent (cont);
+	}
+    }
+    
+    override bool opCall () {
+	foreach (child; list_) {
+	    debug assert (cast(IBoolContent)child !is null);
+	    if (!(cast(IBoolContent)child)())
+		return false;
+	}
+	return true;
+    }
+    // Doesn't support directly setting the value
+    override void opAssign (bool val) {}
+}
+
+/** Create all services.
+*
+* For now, all are under the menu.
+* 
+* Currently all clipboard operations convert to/from a string.
+* TODO: Possible extensions: multi-item clipboard displaying value in menu,
+* copying without converting everything to/from a string. */
+static this () {
+    // Create ContentLists so they have the correct type.
+    new ServiceContentList ("menus.services");
+    // Many use callbacks on a generic class type. For this, we should be sure of the type.
+    auto copy = new AStringService("menus.services.copy");
+    copy.addCallback ((IContent c) {
+	debug assert (cast(AStringService)c);
+	with (cast(AStringService)c) {
+	    if (activeCont !is null)
+		clipboard = activeCont.toString(0);
+	}
+    });
+    auto paste = new AStringService("menus.services.paste");
+    paste.addCallback ((IContent c) {
+	debug assert (cast(AStringService)c);
+	with (cast(AStringService)c) {
+	    if (activeCont !is null)
+		activeCont = clipboard;
+	}
+    });
+    
+    new ServiceContentList("menus.services.calculator");
+    auto inc = new IntService("menus.services.calculator.increment");
+    inc.addCallback ((IContent c) {
+	debug assert (cast(IntService)c);
+	with (cast(IntService)c) {
+	    if (activeCont !is null)
+		activeCont = activeCont()+1;
+	}
+    });
+    auto dec = new IntService("menus.services.calculator.decrement");
+    dec.addCallback ((IContent c) {
+	debug assert (cast(IntService)c);
+	with (cast(IntService)c) {
+	    if (activeCont !is null)
+		activeCont = activeCont()-1;
+	}
+    });
+}
+private {
+    char[] clipboard;
+}