Home > Uncategorized > Improved edit tools for Carmenta Engine

Improved edit tools for Carmenta Engine

A tool is an encapsulation of some user interaction with the map such as panning, zooming, creation of objects and editing of objects. All these operations are provided out of the box and as such they are simple and convenient to use. I.e. if I want to enable panning in the map the only thing I need to do is:

axSpaceX.Tool = new PanTool();

 

It is also possible to write your own tool by implementing the ITool interface:

namespace Carmenta.SpatialAce.Interop.SpatialAceX

{

    public interface ITool

    {

        bool StartManipulation(SpaceX spaceX, int msg, int wParam, int lParam);

        bool Manipulate(int msg, int wParam, int lParam);

        ICommand EndManipulation(bool aborted, int msg, int wParam, int lParam);

        IPictureDisp MouseIcon { get; set; }

        MousePointerConstants MousePointer { get; set; }

    }

}

 

The key methods here are

  • StartManipulation – Check if the interaction should start (i.e. left mouse is pressed).
  • Manipulate – When StartManipulation signals that interaction has started this method will be called instead, allowing the tool to perform whatever it is supposed to do
  • EndManipulation – When Manipulate signals that the interaction has finished this method is called, allowing the tool to clean up. A command can be optionally returned that represents the action, enabling support for undo/redo.

Let’s move forward and see how this can help getting around a limitation of the edit tools (i.e. the move tool and the move node tool). The edit tools will only work for datasets that returns references (to modifiable objects) which according to the documentation is InternalStore, MySql and Oracle and possibly custom datasets. The SQLite dataset that I wrote about a while ago does not return references and thus the edit tools does not work. What is worse is that I do not think that it can by adapted to return references. So, the the question then is; can the current edit tools be adapted in some way so that they will work anyway.

The idea is simple; move the objects into a temporary InternalStore while editing and then (re)insert them. Let’s follow this idea and make a configuration like below

config  

having one persistent store (a SQLite dataset) and one temporary store (an InternalStore) that will be used while editing. Next, we will create a abstract base class for a tool that moves the objects that will be manipulated into the temporary store before manipulation begins and then moves them back into the persistent store when finished. Lets call this class EditToolX. Here is the StartManipulation:

public bool StartManipulation(SpaceX spaceX, int msg, int wParam, int lParam)

{

    this.spaceX = spaceX;

    bool started = toolImpl.StartManipulation(spaceX, msg, wParam, lParam);

    if (started)

    {

        toolImpl.EndManipulation(true, 0, 0, 0);

        started = false;

        originalObjects = GetSelectedObjects();

        if (originalObjects.Count > 0)

        {

            temporaryStore.Clear();

            foreach (GeoObject gob in originalObjects)

            {

                persistentStore.Remove(gob.Id);

                temporaryStore.Insert((GeoObject)gob.Clone());

            }

 

            started = toolImpl.StartManipulation(spaceX, msg, wParam, lParam);

        }

    }

 

    return started;

}

 

Note the trick here – the call is forwarded to the real edit tool (i.e. the move tool) to see if the manipulation should start. If so, I directly end the manipulation. Doing this will have the side effect that the edited objects will be selected. Using this information it is possible to move the objects to the temporary store and then restart the manipulation.

Manipulate can then simply forward the call to the real tool.

public bool Manipulate(int msg, int wParam, int lParam)

{

    return toolImpl.Manipulate(msg, wParam, lParam);

}

 

EndManipulate now needs to reinsert the edited object back into the persistent store

public ICommand EndManipulation(bool aborted, int msg, int wParam, int lParam)

{

    if (aborted)

    {

        foreach (GeoObject gob in originalObjects)

        {

            persistentStore.Insert(gob);

        }

 

        return null;

    }

    else

    {

        var cmd = toolImpl.EndManipulation(aborted, msg, wParam, lParam);

        if (cmd != null)

        {

            cmd.Do();

        }

 

        GeoObjects modifiedObjects = temporaryStore.GetAll(null, null, null);

        temporaryStore.Clear();

        return new EditCmdX(spaceX, persistentStore, originalObjects, modifiedObjects);

    }

}

 

As you can see, this is however, not done in EndManipulation in order to support undo/redo but in a new EditCmdX command. Here is the Do method along with the Insert helper

class EditCmdX : ICommand

{

    // … other code left out for brevity …

 

    public void Do()

    {

        Insert();

        spaceX.Refresh();

    }

 

    private void Insert()

    {

        ids = new Identities();

        foreach (GeoObject gob in modifiedObjects)

        {

            ids.Add(persistentStore.Insert(gob));

        }

        spaceX.View().Selection = ids;

    }

}

 

The command also sets the selection in order to keep the edited objects selected.

Using the EditToolX class we can create two derived classes, MoveToolX and MoveNodeToolX, simply by passing MoveTool and MoveNodeTool respectivly, as a parameter to the EditToolX constructor.

Here is the source code to the updated SQLite dataset along with the new edit tools. The code also provides a new create tool using the same idea as above. The create tool is simplified a bit since we do not need to move the current object to a temporary store. It is enough to save the objects into the persistent store when the interaction ends. Also the SQLite dataset has been updated with a selection bug fix.

Advertisements
Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: