Originally Posted by bdbcat
Maybe you could create some diffs against the current
CVS, and I'll try to merge them.
If this makes sense, please email
the diffs to me directly. email
address in help->Authors tab.
Excellent! I'll gather things up and send them ASAP. I'll briefly list what I did & why here - a few changes had ripple-effect, mostly for your #2 below; hopefully this list will make the diffs easier to follow. Also, you may want (or want me) to change some names. I tried to keep changes inside OpenCPN
to a minimum, but e.g. ChartBase was already defined and used many places, yet has the main chart UI interface...so I created "Chart" that ChartBase inherits from. Maybe should be ChartBase and ChartBaseUI or something?
Also I didn't finish the full leaf-class chart separation (the core
of your #2 below)...I was planning for next week. So I still can't create a chart without it needing lots of UI stuff. I was going to use multiple inheritance to facilitate, but some other approach with delegation and a separate class reference should be just as good - I think this is what you meant but I'm not sure.
(a) move toward letting another app use the chart database:
- moved core
chart enums to chart.h, and pending reorder of ChartTypeEnum (so UNKNOWN == 0, DONTCARE == 1, DUMMY == 2 for the future); I planned to address this db format change automatically due to changes below
- moved key non-UI ChartBase methods to Chart
- separate ChartDB into two classes
: ChartDatabase class is the new one; ChartDatabase doesn't have a notion of stack or currency, it only reads/writes/updates/creates the database and acts as a Chart factory. ChartDB keeps stack and currency, and uses ChartDatabase to get charts. I think better names could be found for the division, but I didn't want to make too many changes.
(b) purify, simplify, and ensure I wasn't screwing something up
- moved Chart & ChartBase toward container classes
rather than interfaces (removed virtuals, added more fields) since I found most virtual overrides just used fields in the parent. The biggest impact was to cm93comp, see below
- moved all public and protected fields into private and added accessor methods, so I could tell & enforce who used what, when...and change the algorithm transparently if needed. The accessors are mostly defined in the header and can be inlined (aren't yet) but I didn't find one that really needed inlining.
- in Chart, made methods, parameters, and results const wherever I could, to assert no surprise changes were happening (e.g. COVR pointers)
- converted pointers and by-value params to references
in some fields and formal params, to assert validity and remove visible indirection
- moved some field setters to protected, to assert that only the hierarchy needs to modify the values
- removed the color scheme on the virtual Init method in Chart, since it is UI-related. I added a non-virtual Init into ChartBase that takes ColorScheme, and in OpenCPN
, it calls that one; that one calls the virtual and does color scheme init. I found that code in a few places, and just consolidated into the one place.
- converted (carefully) ChartTableHeader and ChartTableEntry to objects. They now handle their own serialization/deserialization/cleanup, to help consolidate. I started moving ChartTableEntry to accessor-method use, so e.g. pFullpath became a method that first adds its directory to its delta
path, and during database read, it replaces the common part of the path with the shared directory prefix info.
- rather than an array of structs, changed the ChartTable as a wx array.
- keep the directory list in ChartDatabase, so ChartTableEntries can refer to it
- abstract the access to the directories, so they can keep stringified checksums (separated by ":" as in the original code)
- added a SetCurrent/GetCurrent to cm93comp; it calls the needed Chart methods to change the current
"virtual" chart. I moved the current chart field in this class to private and renamed so I could find all places that changed the current chart. Then I changed those places to call SetCurrent().
1. I have been considering changing the binary chart database file format into an XML human readable/editable format. Of course, it will get larger on disk....
Internal representation may grow, too. I need to add some more fields to database entries.
What is the issue here with Mobile?
for XML as the main chart database, I see pros and cons. The biggest pros: it's readable and human editable, parsing is readily available. The cons: it may be huge for a large chart set. Size may not be the biggest concern; I expect reading the entire thing upon every OpenCPN load could visibly slow startup. My chart db is 1.2MB as binary; from prior calcs I'd say ~260K is string, the rest is number, or ~1MB. I'd guess 10x for XML, or ~13MB read and parse on every load. Parsing will be really fast, but reading 13MB and storing as internal structure will still take a bit of time. It'd be interesting to prototype to see. What do you hope to gain?
Depending on what you want, there are some intermediate points. Reading binary will always be a lot faster. Rather than serializing per-struct, you could serialize per-field (hand serialization) and have more flexibility in version updating. I think keeping read/write in the "object" (ChartTableEntry) helps isolate and makes it robust. But you could also add ReadXML and WriteXML methods...effectively supporting a full chart db import/export approach while keeping binary as the native mode. Again, depending on what you want.
For Windows Mobile, I don't think XML would be any more issue than for other platforms; of course you won't want a DOM-style parser (I think wx is pull-parser style? Haven't looked enough yet). WM has somewhat limited process memory, and OpenCPN keeps the whole chart table in memory. Changing that would be pretty complicated, I think, and I'm not convinced it's necessary. The chart stack isn't a concern because it should always be very limited in size. The cache will need to change for WM, but no big deal; if I remember, we assume MSW has unlimited VM, and WM doesn't. But keeping lots of chart entries all with duplicated strings can take a lot of space. So optimizing the in-memory chart entry helps Windows Mobile. Hope this makes sense, and I haven't misunderstood anything.
2. Also been meaning to "purify" the chart classes, for just the reasons you enumerate. Probably have to define some kind of global_UI_config class, and pass a reference of this to the chart class by method or ctor, so that global statics are not needed, and it will do the "right thing" without a UI... More thought here...Now I have some motivation
Lets see your code...
Makes sense...I'm interested in more of your thoughts there. Along this line, something else that would make sense for UI-less work, is to replace the direct progress dialog invocations with a method callback or pure virtual class (interface); that would allow easy separation of UI for the key low-level chart database and s-57 operations.