From: Brett L. <wak...@ea...> - 2005-12-08 01:28:29
|
I think this would be much simpler a task if we merged ORWindow with MapWindow into a single JFrame, much like StatusWindow is a collection of multiple JPanels within a single JFrame. This merger would also make our overall UI much simpler and more approachable for end-users. Also, instead of Observers/Observables, would it be possible to just add new methods to the model-side to help simplify the bounds checking that we need to do to allow these behaviors? Or is it that the OR is significantly complicated that the methods we used in StatusWindow won't work for the ORWindow? ---Brett. -----Original Message----- From: Erik Vos <eri...@hc...> Sent: Dec 7, 2005 2:45 PM To: rai...@li... Subject: [Rails-devel] OR updates I have restarted working on the OR. This will include incorporating token laying, but I have started with some general improvements, such as skipping or automatically processing steps where the player has no options: - the token step, if the company has no free tokens left, - the revenue step, if the company has no trains, so the revenue is zero. - the train buying step, if there is no room for new trains. However, this turns out to make the task to keep the SR and OR windows up to date even more complicated, so I am now seriously considering to replace the current mechanisms by implementing the Observer/Observable pattern. That will be quite some work, but should very much simplify the updating task when we continue adding features. Erik. |
From: Brett L. <wak...@ea...> - 2005-12-08 21:27:36
|
> What we need is some kind of messages from the Model to the View > about changes of individual values that have taken place > and (possibly) need be reflected in the UI. I think you should revisit how we accomplished this for the StockChart. In StockChart, we just call repaint() whenever the model changes. I don't think there's any good reason why ORWindow needs to be any different. We don't need any sort of messaging subsystem if painting is *only* dealing with drawing the objects that represent the model as efficiently as possible. We can call repaint() as often as we need to. So far, the painting code hasn't shown any indication that it's too slow to be repeatedly repainted. ---Brett. |
From: Erik V. <eri...@hc...> - 2005-12-08 22:41:22
|
> > What we need is some kind of messages from the Model to the View > > about changes of individual values that have taken place > > and (possibly) need be reflected in the UI. > > I think you should revisit how we accomplished this for the > StockChart. In StockChart, we just call repaint() whenever > the model changes. I don't think there's any good reason why > ORWindow needs to be any different. In fact, we call refreshStockPanel(), which completely rebuilds the stock chart. > We don't need any sort of messaging subsystem if painting is > *only* dealing with drawing the objects that represent the > model as efficiently as possible. We can call repaint() as > often as we need to. But we don't. > So far, the painting code hasn't shown any indication that > it's too slow to be repeatedly repainted. Maybe not. But I wonder how this all would work out in a distributed environment. If the server would only send a message to all clients to have them all completely rebuild themselves, that will cause a lot of calls to the server! It seems to me that atomic update messages from server to client would do a more efficient job. Now I don't know for sure if Observer/Observable plus RMI would do that job, but I think it has a good chance. Erik. |
From: Brett L. <wak...@ea...> - 2005-12-08 23:23:35
|
> In fact, we call refreshStockPanel(), which completely > rebuilds the stock chart. I thought we had used repaint(), but after checking CVS, it looks like I was mistaken. However, refreshStockPanel() is doing the job of repaint(). We should probably even rename the method. My main point was that the process of changing the model, then redrawing the affected UI components ought to be just fine for the ORWindow. If the game-specific logic is getting in the way of the drawing code, that could be moved into a separate controller class, so that the drawing code just reflects decisions made in the controller class. Enabling and disabling panels and buttons automatically calls the objects' repaint() method. I don't see why redrawing the window is a thing to be avoided. > But I wonder how this all would work out in a distributed environment. > If the server would only send a message to all clients to have them all > completely rebuild themselves, that will cause a lot of calls to the server! > It seems to me that atomic update messages from server to client > would do a more efficient job. See, now you're getting into a completely different issue. In a client/server setting, I would expect that we want to pass around only updated information about the model and then have clients call their local repaint() to update the UI to reflect the changes. However, I really hope you're not proposing to start refactoring our code into client and server before the game code is complete. ---Brett. |
From: Erik V. <eri...@hc...> - 2005-12-09 22:19:40
|
> My main point was that the process of changing the model, > then redrawing the affected UI components ought to be just > fine for the ORWindow. If the game-specific logic is getting > in the way of the drawing code, that could be moved into a > separate controller class, so that the drawing code just > reflects decisions made in the controller class. > > Enabling and disabling panels and buttons automatically calls > the objects' repaint() method. I don't see why redrawing the > window is a thing to be avoided. It could be a matter of taste, but I find redrawing not very pretty for the eye. I fact, earlier this week I discovered, that the StartWindow (and perhaps also the ORWindow) were completely recreated after each action, because of a bug in StartWindow. I have fixed that and to me it looks a lot quieter now. I admit that repaint() is probably not as bad as such a complete replacement. But I also think that in the StockChart it does not matter much because its squares have a fixed size, but that is not so in the other windows. > > But I wonder how this all would work out in a distributed > environment. > > If the server would only send a message to all clients to > have them all > > completely rebuild themselves, that will cause a lot of > calls to the server! > > > It seems to me that atomic update messages from server to client > > would do a more efficient job. > > See, now you're getting into a completely different issue. > In a client/server setting, I would expect that we want to > pass around only updated information about the model and then > have clients call their local repaint() to update the UI to > reflect the changes. To me this is the same issue in a different setting. > However, I really hope you're not proposing to start > refactoring our code into client and server before the game > code is complete. Hmm, to me this is exactly what we have been preparing ourselves for from the start by applying a strict model/view separation! And to enable use of repaint() in the Status, Start and OR windows I'll have to do some changes anyway. All variable screen elements in these windows are classes in the ui.elements package, and each one could repaint() itself if it would know where to find its value. Currently these elements have no reference to a model class, so the value to paint must be provided from the outside. It seems to me that both in your approach and in mine each screen element *needs* a reference to a model class, where it could retrieve its value from: - in your approach to retrieve the value it should display on a repaint, - in mine to retrieve a new value to display after a signal from the model (to which it has registered as an Observer before). So I think both approaches would benefit from a model/view connection on a granular level, i.e. for each value to be displayed. Seen this way, the Observer pattern would be just a slight extension from a model/view connection that we have to create anyway! My proposal is that I rework the three windows mentioned to use repaint(), passing each field an additional reference to a model class embedding the value to be displayed. So that would streamline things your way. And I can throw away the laborious partial window update methods that I have been creating up to now, and that I want to get rid of. Once that is done, it would be a minor extension to add the Observer pattern on top of that. If only as an experiment so see if it makes any difference. How about that? Erik. |
From: Brett L. <wak...@ea...> - 2005-12-09 23:01:57
|
>> My main point was that the process of changing the model, >> then redrawing the affected UI components ought to be just >> fine for the ORWindow. If the game-specific logic is getting >> in the way of the drawing code, that could be moved into a >> separate controller class, so that the drawing code just >> reflects decisions made in the controller class. >> >> Enabling and disabling panels and buttons automatically calls >> the objects' repaint() method. I don't see why redrawing the >> window is a thing to be avoided. >It could be a matter of taste, but I find redrawing not very pretty >for the eye. I fact, earlier this week I discovered, that the StartWindow >(and perhaps also the ORWindow) were completely recreated after each >action, because of a bug in StartWindow. >I have fixed that and to me it looks a lot quieter now. >I admit that repaint() is probably not as bad as such a complete >replacement. >But I also think that in the StockChart it does not matter much >because its squares have a fixed size, but that is not so in the other >windows. This is exactly the right sort of optimizations needed to make repainting fast. The way repaint() is intended to work is to draw only the segments that need updating, and to leave the rest as is. HexMap's painting methods signals to each GUIHex to have each hex paint itself based on the rectangular bounding box that surrounds the hex. Every time we repaint the map, we're repainting every single hex. >> However, I really hope you're not proposing to start >> refactoring our code into client and server before the game >> code is complete. >Hmm, to me this is exactly what we have been preparing ourselves >for from the start by applying a strict model/view separation! Agreed, but I'm hoping you'll wait to start writing networking code until after we've gotten the hotseat game working. ;-) > And to enable use of repaint() in the Status, Start and OR windows > I'll have to do some changes anyway. This is probably a good thing to do. It makes sense to leverage the infrastructure Sun has built for us rather than to reinvent the wheel. Take note of Sun's guidelines for painting: http://java.sun.com/products/jfc/tsc/articles/painting/index.html The custom drawing code should be placed into paintComponent(), which is one of the three methods that calls to paint() and repaint() are factored into. I'm fairly certain that HexMap and GUIHex work in this fashion. >All variable screen elements in these windows are classes in the ui.elements >package, and each one could repaint() itself if it would know where to find >its value. Currently these elements have no reference to a model class, >so the value to paint must be provided from the outside. That's fine. When painting is requested, we can either pass the elements the location of the information, or they can be taught to know where it is on their own. I think either method is acceptable. >It seems to me that both in your approach and in mine each screen element >*needs* a reference to a model class, where it could retrieve its >value from: >- in your approach to retrieve the value it should display on a repaint, >- in mine to retrieve a new value to display after a signal from the model >(to which it has registered as an Observer before). >So I think both approaches would benefit from a model/view connection on >a granular level, i.e. for each value to be displayed. >Seen this way, the Observer pattern would be just a slight extension >from a model/view connection that we have to create anyway! >My proposal is that I rework the three windows mentioned to use repaint(), >passing each field an additional reference to a model class embedding >the value to be displayed. So that would streamline things your way. >And I can throw away the laborious partial window update methods >that I have been creating up to now, and that I want to get rid of. >Once that is done, it would be a minor extension to add the Observer pattern >on top of that. If only as an experiment so see if it makes any difference. >How about that? Sounds good. Once you start working with using repaint() I think you'll find that adding on Observers will be unnecessary because the painting system already provides the notification to each object that uses the common painting methods. In other words, when we set a HexMap as visible, HexMap's paint() method is invoked. Because HexMap is a JFrame, it also invokes the paint() method of every Swing object beneath itself. So, HexMap will call the paint() method of the JScrollPane we use, and in turn, the JScrollPane will call the paint() method of the JPanel contained within its Viewport, which in turn calls the paint() methods of each GUIHex in the panel. So, as you can see, the fundamental question that you're trying to answer for ORWindow, "When do I draw things?" is answered with, "Whenever someone calls your paint() method." Does that make sense? ---Brett. |
From: Erik V. <eri...@hc...> - 2005-12-09 23:44:29
|
> >> However, I really hope you're not proposing to start > >> refactoring our code into client and server before the game > >> code is complete. > > >Hmm, to me this is exactly what we have been preparing ourselves > >for from the start by applying a strict model/view separation! > > Agreed, but I'm hoping you'll wait to start writing > networking code until after we've gotten the hotseat game working. ;-) Sure, but it will pay off to be prepared! <snip> > Sounds good. Once you start working with using repaint() I > think you'll find that adding on Observers will be > unnecessary because the painting system already provides the > notification to each object that uses the common painting methods. The prime purpose of the Observable would not be send a signal to redraw (that is a UI concern) but to send a signal that the Observable's value has changed (that is a model concern). Whether the UI field then immediately repaints itself, or waits for a repaint of its container, is a secondary matter. In fact I think the latter is better. > In other words, when we set a HexMap as visible, HexMap's > paint() method is invoked. Because HexMap is a JFrame, it > also invokes the paint() method of every Swing object beneath > itself. So, HexMap will call the paint() method of the > JScrollPane we use, and in turn, the JScrollPane will call > the paint() method of the JPanel contained within its > Viewport, which in turn calls the paint() methods of each > GUIHex in the panel. > > So, as you can see, the fundamental question that you're > trying to answer for ORWindow, "When do I draw things?" is > answered with, "Whenever someone calls your paint() method." No, the fundamental question actually was: *what* to draw when it is time for drawing. How to tell a field in these windows that its *value* has changed. OK, needed for any good solution (mine or yours) is that we give each UI field a reference to a model that holds the value to be displayed. We seem to agree on that, and that is the first thing I'm going to add now. Once that is done I think we'll be a lot more flexible. Where we still differ is on the question as to whether a UI field on a repaint() should *always* call its model for the current value (your way), or would have that value already received before through observance of its model (my way). But that is not a big difference anymore, the details will be hidden in a few specialized classes. Good discussion this was! At least it has sharpened *my* thoughts a lot. Erik. |
From: Brett L. <wak...@ea...> - 2005-12-10 02:44:25
|
>> So, as you can see, the fundamental question that you're >> trying to answer for ORWindow, "When do I draw things?" is >> answered with, "Whenever someone calls your paint() method." >No, the fundamental question actually was: *what* to draw when it is time >for drawing. >How to tell a field in these windows that its *value* has changed. >OK, needed for any good solution (mine or yours) is that we give >each UI field a reference to a model that holds the value to be displayed. >We seem to agree on that, and that is the first thing I'm going to add now. >Once that is done I think we'll be a lot more flexible. >Where we still differ is on the question as to whether a UI field on a >repaint() >should *always* call its model for the current value (your way), >or would have that value already received before through observance >of its model (my way). But that is not a big difference anymore, >the details will be hidden in a few specialized classes. Ok, I see what you're saying. I don't think our app is so complex that we really need to worry about delaying updates to the UI. I think we're fine with 'when the UI repaints, it obtains the values from it's copy of the model.' I think using Observers is over-engineering the solution where the existing painting system works well enough and doesn't require building a whole new subsystem. >Good discussion this was! >At least it has sharpened *my* thoughts a lot. Great! I agree, it's good to hammer out these sort of details. ---Brett. |
From: Erik V. <eri...@hc...> - 2005-12-08 19:51:28
|
> I think this would be much simpler a task if we merged > ORWindow with MapWindow into a single JFrame, much like > StatusWindow is a collection of multiple JPanels within a > single JFrame. This merger would also make our overall UI > much simpler and more approachable for end-users. Could be, but that is a separate issue. > Also, instead of Observers/Observables, would it be possible > to just add new methods to the model-side to help simplify > the bounds checking that we need to do to allow these behaviors? > > Or is it that the OR is significantly complicated that the > methods we used in StatusWindow won't work for the ORWindow? The problem is, that many actions in the OR cause changes in both the OR and the Status window. My point is, that I do not want to redraw both windows entirely after each action, because it slows down and makes the UI clunky. Therefore I have so far created lots of methods in both classes that all update part of a screen, and are called from within ORWindow. IMO that is becoming unwieldy. What we need is some kind of messages from the Model to the View about changes of individual values that have taken place and (possibly) need be reflected in the UI. Our rules forbid direct calls, but I suppose a registration-based interface might be acceptable. IMO Events are too heavy. I'm not yet planning a complete overhaul, just an experiment. Erik. |