|
| 1 | +# CalChart |
| 2 | + |
| 3 | +The CalChart program is written in C/C++ using wxWidgets UI Framework to create a cross-platform application. |
| 4 | +CalChart is 3 different things: |
| 5 | + |
| 6 | + * **Composer**: A tool for allowing members of the Stunt committee to create shows. |
| 7 | + * **Viewer**: A way for Stunt members to view their creation. |
| 8 | + * **Exporter**: A way to export the show in a "learnable" form to members of the band. |
| 9 | + |
| 10 | +In order to think about the way that CalChart is architected it is helpful to take a moment to consider how a computer would represent a Show for the CalBand. It would likely have to have an array of Stunt Sheets, each one having an array of positions of each of the Marchers on the field. Each Sheet would likely have some way to describe the Continuity of a set of Marchers from their current position to their position on the following Stunt Sheet, as well as the number of Beats for that particular sheet. |
| 11 | + |
| 12 | +At the core, CalChart is essentially a "drawing" tool where you draw out the position of Marchers (aka "dots"), and then dictate the way that the Marchers will move between sheets via their continuities. Internally it maintains data structures that represents those positions through-out a show, and can calculate if there are incoherences such as when Marchers are not able to make it to their positions or would collide with others. |
| 13 | + |
| 14 | + |
| 15 | +# Architecture |
| 16 | + |
| 17 | + *"The type of UI system you have strongly influences the way you program." - Jeff Lee* |
| 18 | + |
| 19 | +While CalChart is written in C++, it's architecture is more due to wxWidgets, which influences the overall structure and composition of the program. It is advisable to read about wxWidgets at http://wxwidgets.org. |
| 20 | + |
| 21 | +There are different UI windowing systems (like Cocoa for Mac, or GNOME for linux, or QT for cross platform), but wxWidgets was chosen as a good balance of features, cross-platform, and support. This allows one version to be built on Windows/MacOS/Linux, but also means that proprietary UI Kits like iOS would be difficult to support, requiring a complete rewrite. |
| 22 | + |
| 23 | +### Document/View |
| 24 | + |
| 25 | +CalChart is a `wxApp` which heavily uses wxWidget's Document/View model described at https://docs.wxwidgets.org/3.0/overview_docview.html: |
| 26 | + |
| 27 | +> The idea is that you can model your application primarily in terms of documents to store data and provide interface-independent operations upon it, and views to visualise and manipulate the data. Documents know how to do input and output given stream objects, and views are responsible for taking input from physical windows and performing the manipulation on the document data. |
| 28 | +> If a document's data changes, all views should be updated to reflect the change. The framework can provide many user-interface elements based on this model. |
| 29 | +> Once you have defined your own classes and the relationships between them, the framework takes care of popping up file selectors, opening and closing files, asking the user to save modifications, routing menu commands to appropriate (possibly default) code, even some default print/preview functionality and support for command undo/redo. |
| 30 | +
|
| 31 | +The central object that maintains the data model for the CalChart Show is the `CalChartDoc`, which is a subclass of type `wxDocument`. All modifications to the Show are done via the `CalChartDoc`, and modifications are published out to all the `wxView` objects which read from the `CalChartDoc` to update the various `wxFrame` and `wxWindow` objects that constitute the CalChart Application. While there are many custom `wxDialog` or custom `wxFrame` objects created to display different data to the user when using the application, they should generally be thought of as *viewing* the `CalChartDoc` for some specific purpose. |
| 32 | + |
| 33 | +### `CalChartDoc` |
| 34 | + |
| 35 | +The `CalChartDoc` is the *document* in the CalChart Document/View model. It holds the loaded `CalChartShow`, the corresponding `CalChartAnimation`, as well as any temporary data objects that are needed for maintaining the UI appearance. All interactions with the `CalChartShow` object should go through `CalChartDoc`. |
| 36 | + |
| 37 | +##### `CalChartShow` |
| 38 | +The `CalChartShow` is a data object that holds the core parts of the Show. It maintains the list of Marchers labels and instruments for the Show, as well as all the Stunt sheets. A good model for thinking of the `CalChartShow` is that it represents all that should be "Saved" and "Loaded" when you want to continue editing a Show. |
| 39 | + |
| 40 | +##### `CalChartAnimation` |
| 41 | +The `CalChartAnimation` is an object that is created from a `CalChartShow` and represents a fully Animated show. It is used for the various Animation render views to see a top down or 3D version of the show. It can also be used to show the paths a Marcher would travel in the Field view. |
| 42 | +Whenever the `CalChartShow` changes, the `CalChartDoc` will re-create the `CalChartAnimation` so that there is a fresh animation for the various *Views* to use. |
| 43 | + |
| 44 | +### Modification via `wxCommand` |
| 45 | +CalChart utilizes the `wxCommand` objects as described in the [Document/View](https://docs.wxwidgets.org/3.0/overview_docview.html) model: |
| 46 | + |
| 47 | +> When a user interface event occurs, the application submits a command to a wxCommandProcessor object to execute and store. |
| 48 | +> The wxWidgets document/view framework handles Undo and Redo by use of wxCommand and wxCommandProcessor objects. |
| 49 | +
|
| 50 | +When a *View* wants to modify the CalChart Document, it would do so by creating the appropriate `wxCommand`, and then submits that command to the *Document's* command processor. This will cause the *Document* to be modified, and all the appropriate *Views* to be updated. It will also cause the correct "Do" and "Undo" history to be maintained. |
| 51 | + |
| 52 | +### `CalChartView` |
| 53 | +The `CalChartView` is the way that the various `wxDialog`, `wxFrame`, or `wxPanel` objects interact with the `CalChartDoc`. This allows a central place where Drawing and Document manipulation can go through. |
| 54 | +A programming paradigm that CalChart frequently uses is to create a wxFrame object and then assign a wxView to that wxFrame. This allows the frame to be "connected" to the *Document* so that it has a shared "View" into the data model. |
| 55 | + |
| 56 | +### Drawing |
| 57 | +The wxWidgets has a concept of a "Device Context" called `wxDC` through which `wxFrame` objects can "Draw". For CalChart, drawing is controlled via the `CalChartView` (and `AnimationView`) object. The general flow is that when a redraw event needs to occur, the `CalChartView` will access the information on what to draw from the `CalChartDoc` (the Marcher position, dot type, direction, path) and use the `CalChartConfiguration` to determine the draw parameters and call the appropriate draw functions. |
| 58 | + |
| 59 | +### CalChartConfiguration |
| 60 | + |
| 61 | +`CalChartConfiguration` interfaces with the system config for parameters that can tweak behavior and acts as a "cache" for the values. For example, different colors or widths of texts that the user can manipulate for their taste preferences are stored in CalChartConfiguration. Also, values that should be persist between executions of the CalChart program are stored in CalChartConfiguration. |
| 62 | +On `Get`, it reads the values from system config, and caches a local copy. |
| 63 | +On `Set` (or `Clear`), it updates it's cache, and puts the command into a write-queue. |
| 64 | +The write-queue needs to be explicitly flushed or the values will be lost. |
| 65 | +To use a config value, first get the Global config, and then `Get_` the value from it. For example: |
| 66 | + |
| 67 | +``` |
| 68 | +auto save_interval = CalChartConfiguration::GetGlobalConfig().Get_AutosaveInterval(); |
| 69 | +``` |
| 70 | + |
| 71 | +To add a new config value, add `DECLARE_CONFIGURATION_FUNCTIONS` in the class declaration of the right type. This will make the `Get_`, `Set_` and `Clear_` functions available. Then in the implementation file, declare `IMPLEMENT_CONFIGURATION_FUNCTIONS` with the default. |
| 72 | + |
| 73 | + |
| 74 | +### CalChartPreferences |
| 75 | + |
| 76 | +`CalChartPreferences` is the Dialog that is used to interact and manipulate values of `CalChartConfiguration`. `CalChartPreferences` is a `wxNotebook` of different Dialogs that visualize the values in `CalChartConfiguration`, and provide controls for changing their values, as well as a way to visualize what that change would produce. Because we need a way to manipulate the values without affecting the current values, the approach is to make a local copy of the current Global `CalChartConfiguration` and then manipulate that. This is the reason for a "write-queue" in the `CalChartPreferences`; we can manipulate a copy of the Configuration to see the effect without affecting the current settings. |
| 77 | + |
| 78 | +So why use this copy/manipulate/assign paradigm than the Undo/Do approach used in other places of CalChart? Because we don't want to "pollute" the undo stack with modifications of the Configuration. It would be surprising that Undo would change the color of the background in calchart. |
| 79 | + |
| 80 | + |
| 81 | +### CalChart vs CalChart core |
| 82 | +In order to provide a separation between the wxWidgets UI framework part of the project and the generic part of CalChart, we try to maintain a difference between the CalChart Application and the CalChart Core. Code specific that relies on the wxWidgets framework should not be in Core, and objects that can be pure C++ should be in Core. |
| 83 | +What this does is should provide a place where the "How to draw" is distinct from the "What to draw". For instance, drawing a continuity path or a shape can be described as a collection of lines and circles. In the CalChart Core is a `CalChartShape` object, which is interpreted by the varous `wxView` draw routines to draw to the screen or to PDF for printing. |
| 84 | + |
| 85 | + |
| 86 | +# Style guide |
| 87 | + |
| 88 | +We try to follow some program and C++ best practices. A great place to read this is |
| 89 | +https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines |
| 90 | + |
| 91 | +Try to start each header file with `#pragma once`, similar to the `#!` at the top of a unix script file. |
| 92 | + |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | + |
0 commit comments