Could anyone help me with ideas on producing graphic output in a Dolphin
app? I need to plot the values of some numbers coming out of my program, generally simple x-y line plots with time as the x-axis. I had thought of using ActiveX to link my program to Excel, but that looks a lot of hassle, and I only need a small subset of the Excel facilities. So I am working on a Smalltalk system to generate the necessary plots. I have found that everything I need can be done using Canvas>>lineFrom:to: and Canvas>>text:at:, but I am not sure what sort of view to use to provide an appropriate canvas, and what sort of presenter to use with it. I have experimented with using a ScribbleView with a Scribble presenter, since obviously that is a drawing app. When I issue the drawing instructions from a workspace the graph appears exactly as I want it, but as soon as the plot window is covered the plot is wiped out. This does not happen with Scribble, so clearly I am doing something wrong. I suspect I need to have a graph object, which is assigned as the model of a graph presenter and is in turn linked to a graph view. I do not know whether I can use any existing classes as the presenter and view in this set-up; if not, what would be a good point to start subclassing, and which methods would I have to override in my subclasses? I am floundering at the moment, because I am relatively new to Smalltalk. Two further points: a. Am I reinventing the wheel here? There is so much stuff out there in people's goodies packs, perhaps there is what I need already. If so I would be glad of any pointers (or even shameless plugs from authors). b. The primary purpose of the plots is for on-line visual display to users, as part of an interactive analysis. However, users may wish to save some of them for inclusion in reports. So one consideration in choosing what sort of view to subclass is the ability to save the display as a file. The only sort of image saving I can find mentioned in going through the Smalltalk classes is a bitmap, but this is a pain for inclusion in a report, because you have to use it at exactly the original size or destroy the image quality. What is needed is a scalable drawing format like WMF. Do any of the available classes provide the possibility of saving the display as a .wmf file? Thanks for any help. Peter Kenny |
Peter Kenny wrote:
> I suspect I need to have a graph object, which is assigned as the model > of a graph presenter and is in turn linked to a graph view. I do not know > whether I can use any existing classes as the presenter and view in this > set-up; if not, what would be a good point to start subclassing, and > which methods would I have to override in my subclasses? I am floundering > at the moment, because I am relatively new to Smalltalk. That is probably the right place to start. It's the approach /I've/ taken, anyway, so I hope it's optimal ;-) I think the key point that you are missing is that you need to provide your own implementation of View>>onPaintRequired: that does the actual drawing. This is called when Windows decides that it wants your application to refresh part of its display. In this case your View would use the data from the Model to paint the graph on the Canvas. (BTW, Ian's archive and/or Google will show lots of discussion of the finer points of graphics work if you search for "Canvas"). Ian also has a tutorial at <http://www.iandb.org.uk/> (the "buildview" tutorial) which has an example of drawing a histogram as part of an application. That tutorial is very slightly out of date in that it mentions CompositePresenters here and there, but they have been unnecessary since D4 (or D5?) when OA made all Presenters be able to act as composites. > a. Am I reinventing the wheel here? There is so much stuff out there in > people's goodies packs, perhaps there is what I need already. If so I > would be glad of any pointers (or even shameless plugs from authors). Oddly, I don't know of anything that anyone has published. That may be because its difficult to write a self-contained graphing package without it sprawling out to be absolutely /huge/ (see the jFreeGraph package for a -- Java -- example of this). I know that the reason I'm not planning to put my own graph stuff on my website is that the only way I've been able to keep it simple enough to be implementable is to concentrate of the features I actually need to the point where I can't imagine it being any real use to anyone else. > What is needed is a scalable drawing > format like WMF. Do any of the available classes provide the possibility > of saving the display as a .wmf file? I imagine that there is some way to create a Canvas representing a .wmf file, but I've never needed to find out how to do it. For displaying .WMF files, you can use an ImagePresenter and an OLEPicture, e.g: file := 'whatever.wmf'. picture := OLEPicture fromFile: file. ImagePresenter show: 'Basic image' on: picture. -- chris |
Peter,
If you find that your graphing requirements are anything more than just trivial then I would recommend using an ActiveX charting control from within Dolphin. There are a number of these available and the interface methods are easily generated using the ActiveX Wizard. If you don't mind spending some money then we would recommend Steema's TChart control. www.steema.com Best regards, Andy Bower Dolphin Support www.object-arts.com |
Peter,
Further to my previous message, there's a small example (although not very complex) of the use of TChart from within Dolphin at: http://www.object-arts.com/downloads/misc/genelab.png -- Andy Bower Dolphin Support www.object-arts.com |
Andy Bower wrote:
> http://www.object-arts.com/downloads/misc/genelab.png Interesting application... -- chris |
In reply to this post by Chris Uppal-3
Chris, Peter,
> That is probably the right place to start. It's the approach /I've/ taken, > anyway, so I hope it's optimal ;-) Same here, on both counts. > I think the key point that you are missing is that you need to provide your own > implementation of View>>onPaintRequired: that does the actual drawing. This is > called when Windows decides that it wants your application to refresh part of > its display. In this case your View would use the data from the Model to paint > the graph on the Canvas. I think it is better to add yet another object that provides this service to said view, and can be rescaled for printers, etc. > Oddly, I don't know of anything that anyone has published. That may be because > its difficult to write a self-contained graphing package without it sprawling > out to be absolutely /huge/ (see the jFreeGraph package for a -- Java -- > example of this). I know that the reason I'm not planning to put my own graph > stuff on my website is that the only way I've been able to keep it simple > enough to be implementable is to concentrate of the features I actually need to > the point where I can't imagine it being any real use to anyone else. Same here. However, I probably should clean it up and post it. > > What is needed is a scalable drawing > > format like WMF. Do any of the available classes provide the possibility > > of saving the display as a .wmf file? > > I imagine that there is some way to create a Canvas representing a .wmf file, > but I've never needed to find out how to do it. For displaying .WMF files, you > can use an ImagePresenter and an OLEPicture, e.g: IMHO, the better approach is to draw in inches (or mm if you are so calibrated), and scale through the resolution of the output device. Peter, if you create something that renders obects on a canvas, then you can create a bitmap, obtain its #canvas, have your evolving code draw on it, and then use an ImagePresenter to display the results. That approach will save you some hassles with zombie presenters - the voice of experience talking :) Once everything works, you can more easily/safely create a model/presenter pair to make it easier to use. In addition to scaling to printers, another reason to roll your own graphics is that you will not have to worry about installing/licensing an ActiveX control on other machines. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
Thanks to all for the comments. I still haven't cracked it, but at least the
problems are clearer (or at least I think I know where they lie). a. Chris - I see the crucial point is that I must have a method for #onPaintRequired:, which in turn sends #drawOn: to the model (in this case my graph object). I have ensured that the graph object is the model for the view I am using, which is still a ScribbleView, and the object has a #drawOn: method, which I have single-stepped through with the debugger. Everything seems to happen OK, the drawing instructions are issued, but nothing appears. (I know the #drawOn: method is called at the right point, because I put a 'self halt' in it; when I want to close the walkback, the window has to be repainted, which generates another walkback, and so ad infinitum - isn't debugging fun!) b. I have obviously got to learn more about views and canvases than I really want to know if I am going to crack this. One thing bugs me at the moment. Almost all the #onPaintRequired; methods I have found begin: onPaintRequired: aPaintEvent |canvas| canvas := aPaintEvent canvas and this provides the canvas for the #drawOn: method. But inside the method the canvas has extent = 1280@1024 (i.e. the whole screen) and windowExtent = viewportExtent = 1@1. Nothing bears any relationship to the actual extent of the graph window I am trying to draw on. c. Andy - I have thought of the ActiveX route, but if I do that I would use Excel, because almost all the target users are expected to have it already. The problems with that are, first, it looks as though there are different type libraries for the current Excel and for earlier versions, so my program would have to discover which version the user had loaded; second, I want to produce compound graphs consisting of several graphs stacked side by side with the same y-axis, which I have tried to do in free-standing Excel and found very messy if not impossible. I actually have a charting control called ChartFX, which I acquired years ago with Delphi and which I think is licensed for redistribution; I may try it later if the do-it-yourself approach fails. d. Bill - I was thinking in terms of saving the view from the screen as a file. I see now that the save instruction could instead prompt the system to redraw the graph on another canvas, more suitable for saving, and then save that. I thought of a scalable format like .wmf because the users are likely to save the graph as a record of the analysis and put it in a report, which is probably a MSWord document; they may want it as a whole page or embedded in a page, and it would be a pity if they had to come back to my program and rerun in order to resave it at the size needed. I suppose I could provide options to save a bitmap at whole-page, half-page or quarter-page sizes, if .wmf is not possible. e. There is still a question in my mind as to whether Windows provides options for handling .wmf pictures, which maybe OA have chosen not to wrap in Dolphin. IPicture class>>fromBitmap: and fromIcon: refer to constants PICTYPE_BITMAP = 1 and PICTYPE_ICON = 3. Could there be other picture types available? f. I am still puzzling a bit over MVP strategy. I have a group containing a graph model, a graph presenter and a graph view, which is obviously an MVP triad as a component. But where does this fit in the MVP framework of the whole application. Drawing a graph is part of the user interface, not part of the underlying calculation, so it is not part of the overall model. So where does my graph object class belong in the object hierarchy? - all the classes in the main model are under Model. Is this all just a question of labelling, or does it have any implication for the functioning of the system? Sorry that this is longer than most contributions to this group. I grew up in an era when we learned to write essays, not text messages, and anyway writing out like this helps to get it clear in my mind. Thanks again Peter Kenny |
Peter,
I am also looking for a graphic/charting solution for my application. A few years back I spent a week or two trying to use the GDIlibrary stuff. Ended up with a primitive looking solution. (Scaling and inserting labels were problems). Here are some thoughts on your MVP questions: In my case: Model = TPGraphingObject subclass of Model Presenter = TPBarGraphPresenter subclass of Presenter (this has stuff that would need to be refactored if the solution was more complete) View = TPGarGraph Subclass of View Edit the default view of the TPBarGraphPresenter and insert a TPBarGraph view object. (Also, heep in mind the TPBarGraph view is an instance in the TPBarGraphPresenter's view. under some conditions you need to destroy and re-insert it). Then use the TPBarGraphPresenter on the view of your window shell. ... I recently brushed the dust off this code and could not get it to display...then I found the following "magic incantation" in the archives of this newsgroup and it displayed: TPBarGraphPresenter addView: TPBarGraph asResource: 'DefaultView' I never bothered to figure out why this worked or if could be done differently...it just worked and I saw my default model displayed in the view composer and I was happy with that... (As a side note...I could not actually load the package where this code was stored due to some object filer walkback on some view in the package...so I had to open the .pac file with wordpad and cut and paste the source code that I needed...this may be why it didn't all come back together at first) Regarding your conceptual question about the model... yes, TPGraphingObject is not strictly speaking a business model object. It is a runtime only object which is destroyed and recreated for each user action. Each time the user selects a different view of their data, it gets a new TPGraphingObject and sets the model in the presenter to this new object. Hope that helps, Steve Geringer http://www.TradePerformance.com |
<[hidden email]> wrote in message
news:1RxGc.129373$[hidden email]... > > > > Model = TPGraphingObject subclass of Model > Presenter = TPBarGraphPresenter subclass of Presenter (this has > stuff that would need to be refactored if the solution was more complete) > View = TPGarGraph Subclass of View Steve Thanks for the hints - I am trying to follow what you suggest. At the moment I can't generate my view class as a direct subclass of View - or rather I don't know how to generate the view resource to go with it. I have tried using various existing view resources as the starting point (e.g. ImageView.Basic image, TextPresenter.Multiline text and my old favourite Scribble), but they all finish up carrying all the methods of their original view classes, even though I have put them at a different point in the hierarchy. Obviously I am completely confused by MVP. Maybe I should take your hint (that the results are not good enough to be worth the effort) and try the ActiveX route. Thanks Peter Kenny |
Peter,
I would rather have a smalltalk solution than an activeX or third party solution because a few years ago I evaluated Smalltalk Systems WidgetKit/Business graphics for visualAge. http://www.instantiations.com/sts/wkbg.htm I had a terrible time with it. after about two weeks I still could not figure how to get their default labels off of my charts. Plus, after the evaluation expired, I could not even load my own code due to some dependency issues. In any case, last night I spent some time looking at ActiveX charting packages and found a number of them with in the $300-$400 price range. Unfortunately these seem to be licenses per developer machine. (i keep my code on a flash drive and work on diffrent machines depending on my mood). However, I did discover something pretty slick. There were two products which were based on Shockwave flash. They sell you a .swf file and you actually sent it xml to build the chart. This is designed for use with web applications. see... http://www.infosoftglobal.com/FusionCharts/Gallery.asp http://www.infosoftglobal.com/fxgraph/ One plus is that it is animated...you see the chart grow which is kind of flashy (I assume this is optional). Another plus is you don't have to own the Flash MX development tool @ $499. (or whatever tool you would need. they seem to have alot of different tools) The Big question... Does anyone know if/how to imbed a Shockwave activeX component into a Dolphin Application? (I have no experience with imbeding anything activeX into Dolphin smalltalk.) Finally two other things to investigate. Microsoft MSChrt20.ocx seems to come with visual studio which many people own...no need to buy another. Also, there is also a dolphin GDI++ library wrapper...which someone here is working on...not sure if it alleviates any of these problems... Steve http://www.TradePerformance.com |
In reply to this post by Peter Kenny-2
Peter,
> d. Bill - I was thinking in terms of saving the view from the screen as a > file. I see now that the save instruction could instead prompt the system to > redraw the graph on another canvas, more suitable for saving, and then save > that. I thought of a scalable format like .wmf because the users are likely > to save the graph as a record of the analysis and put it in a report, which > is probably a MSWord document; they may want it as a whole page or embedded > in a page, and it would be a pity if they had to come back to my program and > rerun in order to resave it at the size needed. I suppose I could provide > options to save a bitmap at whole-page, half-page or quarter-page sizes, if > .wmf is not possible. When you speak of users embedding the result in other documents, then a meta file makes sense. When you know the output device, I recommend rendering at its resolution, but meta files have their uses too. > f. I am still puzzling a bit over MVP strategy. That will continue for some time, not because MVP has problems, but because it is quite flexible. > I have a group containing a > graph model, a graph presenter and a graph view, which is obviously an MVP > triad as a component. But where does this fit in the MVP framework of the > whole application. Drawing a graph is part of the user interface, not part > of the underlying calculation, so it is not part of the overall model. There is a space/speed tradeoff to consider. Suppose that you have a bunch of nerds that go into concert halls, stand on stage, fire a pistol (loaded with blanks of course) and record the resulting sound at various locations. Sound nutty? It happens. When I was involved with this kind of work, the data sets were a little on the big side for computers of the time. Rendering the various graphs we wanted to see was expensive, and it made a lot of sense to draw to a bitmap that could be painted on the screen rapidly (even rescaled as appropriate), rather than going back to the raw data. I strongly urge you to build something that allows you to render to an arbitrary canvas, and therefore to a display-compatible bitmap. That will simplify your debugging (no partially open presenters to cause trouble). Of course, it can also draw on a view's canvas too, so there is nothing to stop you from directly rendering small data sets. > So > where does my graph object class belong in the object hierarchy? - all the > classes in the main model are under Model. Is this all just a question of > labelling, or does it have any implication for the functioning of the > system? My solution to the problem was to make two graph presenters, one w/o labels, and one that adds labels, using the basic graph presenter to the graphics, and text presenters (static text views) to display the labels. Of course, you can also simply render the text as part of the graphics, and I end up doing that on printers and for "presentation graphics". Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Bill Schwab-2
Bill,
> I think it is better to add yet another object that provides this service > to said view, and can be rescaled for printers, etc. Agreed entirely. I use a "painter" object that is logically separate from the View too -- in fact it's an "editable aspect" of the View so I can still create and configure them in the VC, but am not tied to using them to paint on Windows. > Peter, if you create something that renders obects on a canvas, then you > can create a bitmap, obtain its #canvas, have your evolving code draw on > it, and then use an ImagePresenter to display the results. That approach > will save you some hassles with zombie presenters - the voice of > experience talking :) Once everything works, you can more easily/safely > create a model/presenter pair to make it easier to use. That's a good idea. I tend to do it the other way around, though, and develop with the painter object drawing directly into an open View -- that does have the advantage in immediacy, but I do have to put a on: Error do: [err | err notify] around the painting code in #onPaintRequired: to avoid the risk of a cascade of walkbacks. -- chris |
In reply to this post by Peter Kenny-2
Peter,
> a. Chris - I see the crucial point is that I must have a method for > #onPaintRequired:, which in turn sends #drawOn: to the model (in this case > my graph object). I have ensured that the graph object is the model for > the view I am using, which is still a ScribbleView, and the object has a > #drawOn: method, which I have single-stepped through with the debugger. > Everything seems to happen OK, the drawing instructions are issued, but > nothing appears. Is it possible that your paintng code is buggy ? Or that you are drawing in white on a white background ? > b. I have obviously got to learn more about views and canvases than I > really want to know if I am going to crack this. One thing bugs me at the > moment. Almost all the #onPaintRequired; methods I have found begin: > onPaintRequired: aPaintEvent > |canvas| > canvas := aPaintEvent canvas > and this provides the canvas for the #drawOn: method. But inside the > method the canvas has extent = 1280@1024 (i.e. the whole screen) and > windowExtent = viewportExtent = 1@1. Nothing bears any relationship to > the actual extent of the graph window I am trying to draw on. Yes, that seems to be a problem with Windows, and has been discussed here before quite recently. See the thread from May entitled "Very big bitmap doesn't work". What I do is to use the View's #clientRectangle or #clientExtent to determine what to draw on. Like Bill, I use a painting object that is logically separate from the View itself, so my #onPaintRequired: is roughly like: onPaintRequired: aPaintEvent self painter paintOnCanvas: aPaintEvent canvas in: self clientRectangle. > e. There is still a question in my mind as to whether Windows provides > options for handling .wmf pictures, which maybe OA have chosen not to wrap > in Dolphin. IPicture class>>fromBitmap: and fromIcon: refer to constants > PICTYPE_BITMAP = 1 and PICTYPE_ICON = 3. Could there be other picture > types available? I've taken a glance through the archives, and it appears that nobody has yet produced a wrapper for metafiles (unless there's something in the GDIPlus wrapper ?). It looks as though it would probably be quite easy for someone who knows that level of Dolphin/Windows integration to produce, but then, if it were that easy, surely somebody would have done it by now ;-) > f. I am still puzzling a bit over MVP strategy. I have a group containing > a graph model, a graph presenter and a graph view, which is obviously an > MVP triad as a component. But where does this fit in the MVP framework of > the whole application. Drawing a graph is part of the user interface, not > part of the underlying calculation, so it is not part of the overall > model. So where does my graph object class belong in the object > hierarchy? - all the classes in the main model are under Model. Is this > all just a question of labelling, or does it have any implication for the > functioning of the system? It's really just a labelling issue. The only real difference between a Model and any other Object is that a Model as an optimised implementation of the Observer pattern (#trigger, #when:send:to:, etc). You may want to consider moving your painting logic out of the Model and into a separate Painter object that is owned by the View. That would make sense if the rendering has aspects (color, fonts to use, graph style, etc) that are not logically part of the Model itself. And, from another post: > At the > moment I can't generate my view class as a direct subclass of View - or > rather I don't know how to generate the view resource to go with it. When you create a custom View, you create a view resource and associate it with a Presenter class by evaluating an expression like: MyPresenter addView: MyView asResource: 'Default view'. You only have to do that once. As far as I can see there is no strong reason why you should not be able to do the equivalent from the View Composer, but the fact is that you can't (without some rather desparate hacking, anyway). View resources are instances of the View class that have been converted into ByteArrays using the "STB" mechanism, and then saved in the current ResourceManager. The reason you need to be aware of that is that if you change the definition of the View class (change the instance variables) then stored view resources will likely not load properly. You can add code to your View class to convert old resources to the new format on-the-fly if you want (its straightforward to do), but I assume you don't want to get into that now. If not then you'll have to ensure that you re-execute the above expression to replace the stored resouces if/when you change the layout of your View class. (I'd also recommend using "reference views" wherever possible to embed your custom Views in other composite Views -- hold down the ALT key when you drag a View from the resource list in the View Composer.) -- chris |
"Chris Uppal" <[hidden email]> wrote in message
news:[hidden email]... > Peter, What I do is to use the View's #clientRectangle or > #clientExtent to determine what to draw on. Like Bill, I use a painting object > that is logically separate from the View itself, so my #onPaintRequired: is > roughly like: > > onPaintRequired: aPaintEvent > self painter > paintOnCanvas: aPaintEvent canvas > in: self clientRectangle. > Chris - Yes! It works! This turned out to be the crucial step. I followed all the rest of the instructions (as in Ian's tutorial on 'Buildview') and got nothing, but as soon as I put in the clientRectangle bit the graph appeared. At the moment it is just the curves on the graph, with no grid, scales or headings, but they are just implementation details (famous last words!). Thanks to you, and to all the other people who commented. I shall bear their words of wisdom in mind. At the moment I am just happy to have something that works (sort of), but I may well restructure it to use a separate drawing object - at the moment my #onPaintRequired: calls a #drawOn:withRect: method which sits in the graph object. Some of what I did still seems like a 'magic incantation', as Steve Geringer calls it, but I think I have a glimmer of understanding, thanks to your description. Peter Kenny |
In reply to this post by Chris Uppal-3
Chris
> It's really just a labelling issue. The only real difference between a Model > and any other Object is that a Model as an optimised implementation of the > Observer pattern (#trigger, #when:send:to:, etc). At the risk of confusing Peter (but he seems like he's ready for this<g>), objects can be "models" without being derived from Model. You are, of course, very correct about the optimizations for events, but that is not essential to serve as a view's #model. Peter, it is probably most important that you concentrate on building something (one might say anything) that works without being too concerned with details. Following some of the suggestions in this thread will spare you some of the false starts that a few of us obviously have in common. Once you have something the produces graphic output, you can begin to enhance it. Feel free to ask for advice on where to put your more presentation-oriented features, etc. In general, a good approach to Smalltalk (by no means original to me) is: (1) make it run; (2) make it work; (3) make it fast. Smalltalk's flexibility allows you to make fairly sweeping changes with little backlash (most of the time). Probably the first snag that you should work to avoid is having errors in #onPaintRequired:. Chris traps them (as do I in views); I generally draw to a bitmap first so errors are not a problem, and simply lead to a walkback and then a debugger. In fact, I generally don't bother with a presenter as I start a new graphic; I write code to open an image presenter on the output only when I _don't_ see a walkback :) Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by geringerNOSPAMMM
Steve,
> However, I did discover something pretty slick. There were two products > which were based on Shockwave flash. They sell you a .swf file and you > actually sent it xml to build the chart. This is designed for use with > web applications. That's a nice idea. They even have their website set up so that you can see most of the examples without having Flash installed, which is a nice touch. (Unlike the TChart folk -- why do people /do/ that... ?) I remember sitting around a big table some years ago trying to think of a new product to re-invent the failing company I was then working for. We had LOTS of kit, some decent talent, some money in the bank, but what to do with it... I suggested tools for creating thin-client UIs in Flash, but nobody liked the idea much. We wouldn't have been able to do it anyway, but its nice to think that the idea hasn't died completely. -- chris |
In reply to this post by Schwab,Wilhelm K
"Bill Schwab" <[hidden email]> wrote in message
news:cchk52$ibq$[hidden email]... > Chris > > It's really just a labelling issue. The only real difference between a Model > > and any other Object is that a Model as an optimised implementation of the > > Observer pattern (#trigger, #when:send:to:, etc). > > At the risk of confusing Peter (but he seems like he's ready for > this<g>), objects can be "models" without being derived from Model. You > are, of course, very correct about the optimizations for events, but > that is not essential to serve as a view's #model. > > Peter, it is probably most important that you concentrate on building > something (one might say anything) that works without being too > concerned with details. Following some of the suggestions in this > thread will spare you some of the false starts that a few of us > obviously have in common. Once you have something the produces graphic > output, you can begin to enhance it. Feel free to ask for advice on > where to put your more presentation-oriented features, etc. > > In general, a good approach to Smalltalk (by no means original to me) > is: (1) make it run; (2) make it work; (3) make it fast. > > Smalltalk's flexibility allows you to make fairly sweeping changes with > little backlash (most of the time). Probably the first snag that you > should work to avoid is having errors in #onPaintRequired:. Chris traps > them (as do I in views); I generally draw to a bitmap first so errors > are not a problem, and simply lead to a walkback and then a debugger. > In fact, I generally don't bother with a presenter as I start a new > graphic; I write code to open an image presenter on the output only when > I _don't_ see a walkback :) > > Have a good one, > > Bill Bill Thanks for this advice. I seem to have hit on some of these approaches myself, while trying to follow the advice from people in this group. I now have a graphing system which works a bit. The top-level presenter selects up to three functions of time for plotting and passes them as an OrderedCollection to a Graph class method, which generates a graph object, and then the top presenter assigns this object as the model of the graph pane. The #onPaintRequired: method of the pane sends #drawOn:withRect: to the graph object, which draws itself in the specified rectangle of the specified canvas. The resulting graph scales itself to a 'sensible' range and grid interval and then draws a dashed background grid and the selected functions. There are no labels of any kind as yet, not even scales on the axes. One advantage of the incremental approach is that you can review your design objectives in the light of what you have done. Yesterday, having played with the window with a graph pane working (it redraws instantly when I switch to a different set of data), I realised that a graph for interactive use as a diagnostic tool in an analysis is not the same thing as a presentation graph for use in a report, and it is daft to conflate the two. So I shall not be adding much in the way of labelling to the graph, just numbers on the axes, because all the relevant information is available in other panes. This way I get the maximum space (and maximum visible detail) for the plot itself. If users want to save the plot as a presentation quality graph, that can be added later in a separate editable window. Thanks for the offer of future advice. I feel more confident having got this far, but I shall probably be back! Peter > > -- > Wilhelm K. Schwab, Ph.D. > [hidden email] |
In reply to this post by Peter Kenny-2
On Tue, 6 Jul 2004 11:45:37 +0100,
Peter Kenny <[hidden email]> wrote: > > b. I have obviously got to learn more about views and canvases than I really > want to know if I am going to crack this. One thing bugs me at the moment. > Almost all the #onPaintRequired; methods I have found begin: > onPaintRequired: aPaintEvent > |canvas| > canvas := aPaintEvent canvas > and this provides the canvas for the #drawOn: method. But inside the method > the canvas has extent = 1280@1024 (i.e. the whole screen) and windowExtent = > viewportExtent = 1@1. Nothing bears any relationship to the actual extent > of the graph window I am trying to draw on. Don't let yourself become confused by the way Windows names concepts. Viewport coordinates refer to "device units", commonly known as pixels. Window coordinates refer to "logical units" used by your program. The relationship between those two is governed by a concept called MapMode. Your data point windowExtent = viewportExtent = 1@1 only means that you're working with pixel based coordinates and that the y-axis points down. You should also find a viewportOrigin and a windowOrigin. The viewportOrigin contains the "absolute" position of the origin in device units and is useful if you want to put the origin into the lower left corner of the window. The windowOrigin determines where your "logical" origin lies in relationship to this point. As long as you have GDI-friendly coordinates, you can exchange the headache caused by manual scaling and shifting for the headache necessary to understand how MM_ANISOTROPIC et al. work. BTW: There is almost no difference between drawing into a window and drawing into a WMF or EMF file. You won't need ActiveX components to display those, either, as Windows has builtin functions for handling this kind of tasks. I found the Win32-API help file (old version, available for download) enormously helpful. And much more useable than that modern HTML-help monstrosity. s. |
Stefan,
"Stefan Schmiedl" <[hidden email]> wrote in message news:[hidden email]... > On Tue, 6 Jul 2004 11:45:37 +0100, > Peter Kenny <[hidden email]> wrote: > Don't let yourself become confused by the way Windows names concepts. > A bit late - I am thoroughly confused, though the fog is lifting a bit. I have a method which works, though I'm not quite sure how, and I shall stick to it! > Viewport coordinates refer to "device units", commonly known as pixels. > Window coordinates refer to "logical units" used by your program. > > The relationship between those two is governed by a concept called > MapMode. Your data point windowExtent = viewportExtent = 1@1 only means > that you're working with pixel based coordinates and that the y-axis > points down. > > You should also find a viewportOrigin and a windowOrigin. > The viewportOrigin contains the "absolute" position of the origin in > device units and is useful if you want to put the origin into the lower > left corner of the window. > The windowOrigin determines where your "logical" origin lies in > relationship to this point. > Chris Uppal in working with the client rectangle. I know that my coordinates are in pixels relative to this rectangle. > As long as you have GDI-friendly coordinates, you can exchange the > headache caused by manual scaling and shifting for the headache > necessary to understand how MM_ANISOTROPIC et al. work. > > BTW: There is almost no difference between drawing into a window and > drawing into a WMF or EMF file. You won't need ActiveX components to > display those, either, as Windows has builtin functions for handling > this kind of tasks. This looks interesting, and I shall try to follow this up when I can. I am using screen based graphs only at present, but when I want presentation ones I shall know what to do. > > I found the Win32-API help file (old version, available for download) > enormously helpful. And much more useable than that modern HTML-help > monstrosity. > > s. Thanks for the tip. I think I may have a copy on my old machine. Thanks and best wishes Peter |
Free forum by Nabble | Edit this page |