I have a rather large application I'm trying to make in Visual-C++, and I am now trying to add undo/redo functionality.
Having a rather large amount of events (button clicks, label text changed, etc.), I would like to find a way to undo/redo without adding code to every function.
For Instance, I would like a class that can read every event done and store it automatically. Then in my undo/redo events, I can just get the latest action stored.
If that is not possible, I would not mind some other way.
Any help?
Declare a class that represent two operations - undo and redo.
Also create two vectors of that class.
For each operation you want to apply undo/redo, push an instance of that class into the undo vector. There should be as many derived classes as there are opreations you want to undo.
For example, if a button click paints the background to green, you create a class instance whose undo metdho paints the background to the previous color, and its redo method paints the background to green, and stuff it into the undo vector.
When you undo - you pop the last class instance and call its undo method, which will paint the background to the previous color. Then you push it to the redo vector.
When you redo, you pop the redo vector for the class instance at the top and invoke its redo method, them stuff it back to the undo vector.
There are some corner cases (boundaries), you'll tackle them when encountered.. :-)
Do all of your events pass through a queue of some kind? by default in c++ there is no queue like this (there is a windows os level event queue, but that is likely managed already and unusable in c++-cli and you did not indicate if this closely mapped onto your problem), there may be some other construct I am unaware of.
If you have some central queue, then it is just a matter of capturing events as they pass through and knowing how to undo each action. If no central queue is present then I see no other way easier than changing each undo-able function to create an undo object of some kind and storing it in and undo queue of some kind.
In a pure .net or a C++ environment without a large central work queue I would make a class that is and undo entry, that implements a method/member function to undo and another to redo/do the work. But for just undo functionality, this could be just a .net delegate or a c style function pointer, and a list of arguments. If you make an action undo/redo class it could be a template or generic that stores pointers/delegates to the the do and undo functions, and a list of arguments from when it was originally called.
These can be run to undo the actions that have been done. They will be inserted into a queue container of some kind, the kind of container doesn't seem to matter as longer as it preserves order, your should pick the best std, .net or other container for your application. You can discard older ones when you no longer need them. When executed the entry last inserted into the queue must be removed to preserve consistency.
If you also need redo functionality, then your queue of actions done must be iterable, and it would be easiest to use the class that was and action had a method/member function that could undo/redo the desired actions. You would have and iterator, pointer, index or marker of some kind indicating how far back you have undone. Every time an undo is requested you must move the marker backward (earlier chronologically) and execute the undo command at that point in the queue. If a redo is requested then the current item indicated executes its redo instruction and then the iterator is advanced forward (chronologically) through the queue, or ignored (I presume) if you are at the forward-most item in the queue.
If you wanted to go off the deep end, which you have no way indicated you want to, you could center you app around the action queue. You might not need to change you functions implementing this approach. Your user interface (I assumed, could just as easily be your API) functions, insert actions (which support doing and undoing) into a queue, and then command the queue to do. You would not have to change your existing functions if their side effects are known and reversible. However, you would need to change all the callers to make actions instead of directly calling, and you would need to write counterparts that do the undoing.
I've tried to achieve something like that in a small experimental library: https://github.com/d-led/undoredo-cpp. It contains an implementation of a TransactionStore similar to what CodeChords man suggested. You might need to really add functionality to each of your undoable objects, and also take care of object lifetimes, in case your actions involve object construction or destruction
Related
I am attempting to create a framework where I can have multiple events all use the same room.
For example, the player triggers an event and the event builds the room with the passed in variables.
I am having trouble making the room dynamic. I want the room and the objects in the room be reusable for every event. This includes the buttons as well.
Is this possible to do?; OR
Do I have to create separate rooms for each unique event I wish to create?
The game is mostly menu based (like the game "Long Live The Queen") if that helps.
To answer simply, yes it is possible.
There are a lot of cases where I have been able to fit a lot of stuff into a single room in Game Maker. Here are a few ways to achieve this "dynamic" game creation:
Files and Scripts. You can use a single room to hold a variable number of levels by storing walls, floors, player positions, events, etc inside of a file. You can make a script that takes the filename (your "passed in" variable) and then let it simply create all of the instances inside the level for you in that room. You can also have a function that cleans up the room to prepare for another level to load. The side effect though is that your uniqueness is limited to what information can be stored in those files. You can store menu options and text dialog too if you wish.
"Unique" Objects. Game Maker is an IDE. There is nothing stopping you from making new objects in the editor for a unique case and then adding a handler in another object to create it on demand. You have to manage switching between them though.
Make a "manager" object. It can handle all of the events of something happening in-game (and in that room, for that matter). Plus also it can be used by objects to store non-global variables before being destroyed. For instance, if a character dies, it can set a variable in a manager object to "true", which would trigger a boss to appear.
In terms of manipulating object events dynamically though, unless you are running something like Game Maker 8, that is no longer possible. I say this because prior to GameMaker:Studio, object, sprites and others can be created dynamically in game via functions like "object_add()". Of course, these are obsolete and can no longer be used. Nevertheless, there are always ways around it.
I've used glutdisplayFun(void(*func)) in several of my program to sets the callback display to the current window.And by the use of it, i've rendered different things on the screen. By looking at the documentation of glut, passing null to it is illegal and we can't deregister it also.
The problem is that as we can't deregister it and i write a set of code to display the mainmenu(i.e as shown in the game). And i like to change to next window on the keypress(i.e play the game by clicking on the option play present in the mainmenu).
How to make the glutdisplayfunc call to the mainmenu inactive and and to set the glutdisplayfunc() for calling the next window.
std::%something%<std::function<void(void)>> displayFns;
void myDisplayFunc() {
for (auto& displayFn : displayFns)
displayFn();
}
Now register myDisplayFunc to GLUT and change the displayFns collection.
As for something, map<int, function<...>> would be a good start. Unordered map if you can guarantee your code doesn't need to be called in order. It starts to resemble good old BASIC times with line numbers, but I said upfront it will be a simple answer.
That's not how I would do it, but should do the trick for a quick'n'easy solution.
Funny thing with this is that you can create sets of those to have one element appear in more than one choice rather easily. So maybe it's not that bad after all.
Qt::QUndoCommand problem and possible solutions.
We are developing an application of 3D editing in Qt.
We need to implement a "stack of operations" which allow the user to call undo-redo on his operations.
We are using QUndoStack with QUndoCommand Qt classes.
The application is based on the MVC pattern so the View (QGLWidget) knows how to draw the scene structure.
We have sliders (QSlider) to translate/rotate/scale the 3D objects (Meshes), and we need to show the effect of the transformations in real-time.
For example if I have selected an object and I'm moving the "X Translation Slider" I want to see the object moving along the X axis while I'm dragging the slider.
The problem is to get the real-time editing working with the stack of operations. In fact the "undoable" operation who should be pushed on the stack is the total slider movement (from the pression to the release of the slider).
We find out 2 ways of doing this:
While I'm dragging the slider (at every valueChanged signal) the
transformations are applied to the model and the QGLWidget updates
straight after every slider tick. At the release of the slider the
command must be pushed in the stack. QUndoStack automatically calls
the QUndoCommand::redo() action when a command is pushed. To prevent
the operation to be executed twice (the first time to grant the
real-time effect, the second at the QUndoStack::push() call), before
the call of QUndoStack::push() The inverse transformation is applied
to the object (obtained from the total slider movement) and then I
push the command to the stack.
QUndoStack tryes to merge command when they have the same result
from a call to QUndoCommand::Id(). While I'm dragging the slider (at
every valueChanged signal) a QUndoCommand is generated and
immediately pushed on the stack, the stack merges it with the
command at the top if they have the same Id(), then the stack calls
the redo() for the command who is being inserted, then the QGLWidget
updates and the real-time effect is obtained.
With the second one an instance of the "Command" class is generated every slider tick, while with the first one the real-time operation get's reverted just to push a command and to stay in a consistent state.
What solution is better in terms of "good programming"?What is better in terms of performance?
I think you're looking for QUndoStack::beginMacro() and QUndoStack::endMacro()
Which can be used to merge a series of commands in the undo stack so that they're done/undone as an atomic operation.
Chris is correct, you could use macros as well as your proposed solutions. But I don't think his criticism of 'overly complicated' is fair: the Qt mergeWith AND macro mechanisms are intended for your purpose.
I would not worry about the performance of any of the solutions, until you find that the performance is a problem. Get it working, then test for performance, and then fix any performance issue. You can't know until you try it whether the generation of excessive commands(that are then merged) or your inverse transformation is a performance problem.
Another solution: on the first tick, push a command and keep a reference to it. On subsequent ticks, update the command and perform an increment of transformation?
(There is a related problem where a command is pushed but a user cancels the operation. For example, what if the user drags the slider, but releases the mouse outside the slider? Is the slide canceled? Search for "transactional undo command". It reimplements redo so that it does nothing the first time it is called as the command is stacked, and has a commit() or rollback() method that is called later.)
(I learned something from your post: when self.mergeWith(other) is called, Qt calls the redo method of other. That's not clear from the documentation.)
Let's imagine you have a fullscreen C++ desktop application that consists of several screens with each of them having a distinct function and a ViewController with appropriate models as well. For example a set of the following very simplified screens:
Quiz: The user is navigated through a set of multiple-choice questions.
Quiz Results with Statistics.
Information: The user is presented with information about a specific subject.
Menu (Quiz, Information, Exit)
Judging by the GRASP principle Information Expert, each ViewController will know best when it is finished and time to move to a new screen. Yet by the same principle, it is not the right place to decide what the next screen should actually be. In this rather simple example, one could argue it would be okay but in a more complex application, it will undoubtedly lead to duplicated code and logic as well as higher coupling and lower cohesion. There is also the problem that you would have to create the new widget and controller within the current screen's ViewController which brings all sorts of new problems and at least by the Creator principle, it is not the right choice. You would have to introduce a Factory to alleviate some of the problems, amongst other things.
So, the next logical step is to introduce an ApplicationController with the sole responsibility of managing Views and their controllers including the navigation flow from one view to the next.
This still leaves one problem wide open in my opinion: How to signal the ApplicationController that it is time to move to a different screen and hand over the control to that object properly?
One could use the Observer pattern, for example. Yet what if you have an expensive View active at the moment and want that one destroyed once the new screen is active? If the current ViewController signals the ApplicationController that the next screen should go up, it can manage everything up to the point where it would destroy the currently active screen which it cannot do because the current call comes from exactly that object. Apart from several other problems with that approach.
So my question is (and sorry for all the verbose introduction :P): How do you properly implement a navigation flow from one fullscreen widget to a different one with MVC which solves the above problems, splits the responsibility between the View- and ApplicationController and is nicely object oriented in terms of coupling and cohesion?
Sometimes you miss one detail in your thought process and you open up a whole can of problems without even realizing the mistake you made.
In this case the detail was that you can naturally post asynchronous as well as synchronous events. If you have to make sure that you are no longer in the context of the event posting method, post an asynchronous event. Once you receive that event in your handler, you can be sure that the context was left. And for example you can safely delete the object, if you so desire. Naturally the event handler should not be in the context of the same object that you are trying to delete.
For completeness: In Qt, you can specify for each signal/slot-connection you make with connect(), that it should be of type Qt::QueuedConnection. If you raise a signal, it won't be delivered until the control is back to the thread's event loop. Normally, Qt::AutoConnection is used which delivers a signal at the time it is raised (Qt::DirectConnection) if the receiver is in the same thread or falls back to queuing that signal (Qt::QueuedConnection) if the receiver is in a different thread.
In wxWidgets you can queue events with wxEvtHandler::QueueEvent(wxEvent* event) which is available through the Application singleton for example.
I use CListBox::SetItemData to store a pointer to some data in my ownerdrawn CListBox-derived class, and I'd like the listbox itself to keep track of it and free the memory when its no longer needed.
For that I'd need to be notified each time an item is deleted (including LB_RESETCONTENT and every possible other case where an item is deleted). Is there an event or events that I can handle to achieve that?
As its owner drawn with one of the LBS_OWNERDRAW* styles you can look out for WM_DELETEITEM;
Sent to the owner of a list box or combo box when the list box or
combo box is destroyed or when items are removed by the
LB_DELETESTRING, LB_RESETCONTENT, CB_DELETESTRING, or CB_RESETCONTENT
message. The system sends a WM_DELETEITEM message for each deleted
item
No. A ListBox only generates notifications for things that the user does. The user cannot remove or add or empty a list box, that can only be done by your own code. So the philosophy here is that the control doesn't have to tell you about something you already know. You can arbitrarily generate your own message in the code that modifies the content. But of course inheriting your own class from CListBox and adding your own virtual methods would be better.
Since you're subclassing the listbox already anyway, the 'proper' design would (IMO) be to add data management functionality to the listbox, which would then know when items are removed and can delete the data as required. What I mean is, let's say your list keeps track of people, you'd add AddPerson(Person p) and RemovePerson(Person p) methods to your class. The implementation of RemovePerson would remove the respective entry from the list, and delete all data related to it. So don't use CListBox::DeleteString to remove things, use the higher-level API that you implement yourself.
It's easy - just subclass the list box and add message handlers for LB_DELETESTRING and LB_RESETCONTENT
See here for details:
http://www.codeguru.com/cpp/controls/listbox/article.php/c4759/CListBox-with-the-Horizontal-Scroll-Bar-that-Works.htm