Is it possible to suppress a re-render? Suppose I dispatch handler [:a] and handler [:b] on state db-0. Such that:
db-0 -> [:a] -> db-1 -> [:b] -> db-0
The end state is the same but two re-renders are made. I do not wish for a re-render of the intermediary state db-1. A re-render, if necessary, should only happen after both [:a] and [:b] have both been applied.
Background
If a dispatch causes a change to app-db, an animation frame will be "scheduled" to handle any necessary re-rendering. As a result, that re-rendering will occur about 16ms later.
If, in the meantime, another dispatch happens, then its changes to app-db will also be handled in the already-scheduled, upcoming animation frame.
By the time the AF rolls around, the changes for both dispatched events will be manifest in app-db.
Your Scenario
So, as you can see, the dispatch of [:a] will cause an AF to be scheduled, however before it is run, your dispatch of [:b] will further change app-db back to its original state.
When later the AF runs, all the layer 2 subscriptions will run, all of them, because app-db was changed (in some way as yet unknown) BUT because previous values will = new values, the signal graph propagation will be pruned, and no re-renders will ultimately run.
Related
In a source file called gui.clj, I define a frame, fr, that holds the window for my application, like this:
(def fr (frame ...))
and a run function that sets up fr and causes it to repaint when data changes, something like this (modeled on scribble.clj:
(defn run []
(-> fr add-behaviors pack! show!)
(when-data-changes
(swap! state assoc :shapes (dot/g->seesaw t/ws))
(repaint! fr)))
As I'm messing around in the REPL, I often modify a source file and then call c.t.n.repl/refresh. When I run run again, it puts up a new window, leaving the old window on the screen. How can I make my (newly updated) code operate on the same window even after a refresh?
You can put your application's state (containing the window object) into a defonce in a separate namespace and call disable-reload on the namespace. This will prevent the reloading of the namespace when (refresh) is called thus keeping the original state (containing the original window object).
In practice, however, it is usually better to clean up and restart the application on reloads. It can be dangerous to hold to obsolete objects from the previous state of some namespace. Use component or mount to manage the application state.
It sounds like you want to have a bit of a "lifecycle" for the stateful parts of your program, somewhat like
make it exist if it does not
let it run
clean it up
and would like this to happen when you reload. You can have the same window continue to exist and get new contents by adding code to your clean-it-up function that clears the window, or you can close the window and create a new one for each cycle.
I have used the component library for larger projects using this style and it was very effective, though it's a bit of a lifestyle change to get used to it.
for your case you may just want to initialize an atom fro store the active window then define the three basic lifecycle functions that opperate on that atom's contents. (and put the actual atom in a defonce)
How to use the given method in swift 3.
func addAndSetupAccessories(completionHandler completion: (Error?) -> Void)
I observed, the completion handler got invoked immediately although the HomeKit set up page(very initial page of Homekit accessory pairing in iOS 10) was front and the accessory pairing process was not over. If this is the case, how to invoke any operation after the set up process gets completed? How to get if the set up process is over??
The only way to handle it is to assign a HMHomeDelegate to the target HMHome object before calling addAndSetupAccessories and keep track of accessories that are added. The dialog only allows setting up one accessory at a time, so you will get at most one non-bridged accessory and potentially zero or more bridged accessories.
When your view controller that is hosting the process gets viewDidAppear called the second time, check if you have set up a non-bridged accessory. If not, it was either cancelled, or finished with an error, which Apple's dialog would have already handled.
Note that this will not work on iPad as it shows a popup, so viewDidAppear won't be called when pairing dialog is dismissed. I'm not sure it's possible at all to find out when the process finishes on iPad.
UPDATE
iOS 10.3 completely changes this behaviour, and the completion handler of addAndSetupAccessories is now invoked when the pairing dialog is closed (as it should have been to begin with). If nothing was paired, the callback will get an error with code 23, HMError.operationCancelled.
You still have to keep track of added accessories via HMHomeDelegate callback, but post-setup handling should move from viewWillAppear to the addAndSetupAccessories callback.
To the surprise of no one it's not documented or mentioned anywhere in any release notes.
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.)
I have an ember.js application. It shows a list of "Problems". Once loaded, the first action taken to select (click) an individual item from this list has a 1-2 second delay. No delay is ever present on subsequent clicks.
The delay is not from the server, if I remove all content from the view/template, the delay is still present.
The delay is not in rendering. If I instrument the rendering process (as described in this answer: https://stackoverflow.com/a/15129150/1167846) nothing happens with rendering at all during that time, and the list displayed at the end shows nothing that indicates a multi-second pause.
If I use console.log all over the place, the click event appears to make all the necessary changes in my code (selecting the item as "current") without any delay.
How do I figure out where this delay is coming from?
In the documentation of Ember.StateManager it's said that : "Inside of an action method the given state should delegate goToState calls on its StateManager". Does it mean that if I send an action message, I necessarily need to transit to another state. Is it possible to stay in the same state but doing some task by sending an action ? For example, I'm in a state "loading" and I run two actions "preprocess" and "display".
Very simply: an action message may but does not have to transition to another state.
Something you didn't ask, but is related and important: it is a bad idea and bad design to call goToState in an enter or exit method.
When dealing with statecharts in general, you can do whatever you want. It's not mandatory to switch states in an event handler. A common case would be an event handler that shows a cancel/save dialog. You can easily put the dialog on the page in the event handler, and proceed accordingly depending on which button is pressed.
A separate question is should every event handler basically just go to another state. In the above scenario, you can certainly go to a "confirm" state, the state-enter method will show the dialog, and there would be two handlers, one for each button. Those handler would in turn go to other states.
Both design choices I think are equally valid, at least in that scenario. If you choose to implement a separate state for every action, you will end up with a lot of small but concise states. If you choose to do stuff in the event handlers themselves, your states will be bigger, but there will be less of them.
One thing I will say is if an event handler is getting complicated, you are probably better of with a new state. Also, be consistent.
For you specific scenario, if I'm reading it right, you want to load data and then change the display to show the data, based on an event. In this case, I would use new states.
So you press a button that starts the process
In the event handler, go to some sort of 'MyDataSection' state
Initial substate is 'loadData'
Enter state method of 'loadData' starts the loading process
Event handler 'dataLoaded' in 'loadData' to handle when the data loads; this means you need to fire an event when the data loads
'dataLoaded' event goes to the 'show' state
show state shows the view (or removes activity indicator etc) and handles any events that come from the display.
What's good here is that if you have multiple ways to get to this section of the app, all actions that lead to this section only need to go to this state, and everything will always happen the same. Also note that since the view event handlers are on the show state, if the user hits a button while the data is loading, nothing will happen.