Mercurial > projects > mde
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; +}