Sunday, 31 January 2010

Ground to a temporary halt

Set of on a mission to try and make the title (and all) text objects editable using JTextField. Very tricky - I have JPanel in which all the graphical objects go, but am not using swing components, it's all hand drawn. Trying to mix in a Swing component just got very messy. Backed it all out and will use a dialog box for now.

So after losing time on the above journey, took a look at how best to implement mouse actions. So the panel can have mouse listeners on it, and in the events you can decide what to do. The worked example I have uses lots of technical factory methods to generate different classes depending on what the user selects etc.

I though maybe we could implement the following:
  • mouse click is select the object clicked on
  • right mouse click on object, pop up menu for altering object, including delete
  • right mouse click not on object, pop up menu including create object at click point (if adornment) or at cursor if note or bar dressing
  • click in bar space but not on object is move insert point to there
Do we make a mouse mandatory or do we have keyboard equivalents for these? Not sure if there's a keyboard equiv of the mouse listeners, got to be I guess.

Will expand up on these thoughts later ...

Good Progress

That's the basics all in place, the app can create a new window, model, view and call each component to draw itself.

Only the text component is implemented but this shows the whole application framework, works!

Next items to work on are:
  • a simple dialogue to allow the user to specify properties of the score, e.g. the size and orientation of the paper, how many staff lines per page
  • controllers for the text components, mouse, keyboard, actions for adding new, moving, deleting (ensuring can't delete title!)
  • file open, save, saveas
  • work on the staff line class - draw the lines
We're inching ahead here!

Saturday, 30 January 2010

Implementing the model

The model contains Collections of adornments and staff lines.

The adornments are the textual elements the author may wish to put in the score. Going to start with saying they can go anywhere on the page for now. In the next revision, I'd look to have a header collection and a footer collection which repeats on each page. At the moment, by implication we're talking about a single page being all that's supported.
Each staff line object contains two further collections, one for bar elements, such as the various different bar separators (single line, repeat bar mark, time signature, curly thing that means treble or the bass one!), and a second collection for the note elements that go on it.
That's what's decided for now. The critical piece now is how to store representations of unison markings / groupings, and regular and irregular groupings of note, e.g. a triplet.

Initial thought is somehow tagging the start and end note of a group, ie a group object with a reference to the start and end notes, and would the notes themselves somehow need to know they delimit a group? Would need to be outside the staff line concept as groups can cross bars and lines on a page. Going to park this and think it through.

So back to the collection of adornments. This is implemented as an ArrayList, as it allows positional access, i.e. by element number x, and you can iterate backwards and forwards. The thinking here is at some point we're going to need to understand which graphical widget resides at a particular screen location (e.g. when user clicks the mouse there). While managing the contents of this list we keep the order as being leftmost and highest object on the page at the beginning of the array, and the lowest and rightmost at the end of the array, and all those in between in descending order (visually).

The exception to this is element 0 in the ArrayList is always the object containing the score title. This is required for other uses in the program so we need to be able to reference it at any time, including when we've loaded the model from a file, we can easily extract the title for the rest of the programme.

Why store it in the list? My thoughts were for ease of scanning the page for graphical objects. The option would be when performing the scan (which I'm yet to confirm I need to do!), to check the title object, scan the adornments and scan the staff lines. Could easily be persuaded to abandon this approach and store it separately as it won't change much once set, and so could be a separately searchable object, and check for it last.

To layer or not?
Also toying with the idea of layers on the page, e.g. layer 1 is the adornments, layer 2 is the staff lines and bars etc, and layer 3 the notes. Concept is you select the layer you are editing, optionally hiding the clutter of the other layers contents. Leaving the "clutter" visible but dimmed may help if you are e.g. moving bar lines about. It's a level of complexity to implement but also a level of complexity for the regular user who may just expect to click on an object and manage it, not having to worry about which layer is showing.

Simple is best in my humble opinion, so we'll start with a single layer. It's going to be hard enough managing viewports and scrollable regions, zoom etc, without another level initially. Should be able to fit in a later version if it's really wanted.

Graphical Objects
An abstract class called ContentBase is now implemented. It contains the data common to all graphical objects which get stored in the model, including the get/set methods.

On top of this we have ScoreText, which is the implementation for any textual adornment, and ScoreStaff, as the object which stores bars and notes on a particular line.

So at the time of writing we have a working application, with a basic model and view, minus the code to actually paint any of the graphical widgets in the app yet ;-) writing that now!

Off to do some adornment implementing and muse over the grouping conundrum.

Thursday, 28 January 2010

The Model for a Score

Thinking so far is it stores a number of important data items:-
  • Attributes for the page, e.g. landscape, portrait, paper size, number of lines per page, eventually include options for layout of lines
  • List of general adornments, e.g. text items (title, author, type [march, reel], basically any random text); graphic items such as logos, open ended so more type can be added (shapes?)
  • List of lines (staves?)
  • List of items that sit on lines, e.g. time sig, bar open / close, note, note group (hmm, when group crosses line? multiple grouping levels), unison group
One of the things that's bothering me is if each line contains its own list of items that sit on it, does that make things easier or harder for later in the programs life, when perhaps it can auto layout and move bars between lines. Perhaps a "paragraph" paradigm can be adopted where the list of items that go together, e.g. a logical part, are maintained as one list and that can be stretched, or moved around on the set of lines that contain it. Would be complex because don't want to constrain thinking to straightforward march scores etc, need the freedom to express any musical construct, e.g. for a drum fanfare / salute.

Should we perhaps not constrain by line at all, and layout of what sits where is managed by a view? Yes probably, but it needs to be persistent therefore should be stored in the model, talked myself out of that one - I am inclined to think that this is all about the manuscript therefore precise storage of the relationship between a note and the line it sits on is therefore important, duh.

So really until I decide on how to best store all the musical constructs, dependent on how they will be used, and how to deal with groups (simple groupings like unison markers, and then other more complex groups like irregular and regular groups, which may in turn be nested), there's no implementation to be done other than the adornments and page layout pieces.

Might be worthwhile implementing those, as that will bed down for me all the 2d graphics libraries, collections etc and improve my overall understanding of views and controllers and their interaction with the model.

That's what I'll do then! See you in a month or so!!!!

Wednesday, 27 January 2010

Hallelujah Moment Number 1

So the windowing and menuing is all working. I have a Set of editor objects, which is maintained through control of creation, deletion and amendment of editor objects. Each is responsible for providing it's title which is used as the menu item, and a custom action stores the editor to title relationship, so it can be referenced when the user selects the menu item, to allow that window to be popped to the front. Magic!

Learned a lot about menus, collections, actions getting this bit right - good stuff.

Reference to the Apple Human Interface Guide means we now have a File->Close option which closes the current editor, but leaves the app running and of course any other open editors.

Starting to think about storing the attributes of a score now. Going to use a Model View Controller paradigm, where there's a model object which holds the data associated with the score, e.g. title, page layout, lists of other decorations, list of staff lines, list of notes, list of bar seperators, time sigs, etc. All the functions for setting and getting values are contained in the model, and it tells any Views watching it when it changes, so they can redraw. Typically the changes are the result of input from a Controller.

I'll understand more, when I've implemented it!

Saturday, 16 January 2010

collections, windows, focus etc

OK, so maybe a List collection is the right way to store all the open JFrames (so we can call requestFocus to switch to it [I think]) and the score name to put in the menu text.

I can see there being a future request to enhance what gets shown in the menu text if a user has two different scores open but both have the same score name, rather than filename. Let's park that for now, I think the hardest bit to get working will be the storing of the JFrames in a suitable collection.

Don't know if by providing it's JFrame object, an editor could tell the control object which entry in the List it is, so it can be deleted if it's closing, or perhaps it's opened a different score and needs to change its title. To be tested.

Got a problem with the menus at the moment in that I thought I could create one central JMenu object for the Window menu and have all the different JFrames menubars hook up to it. Nope, it deregisters from one menubar when added to another. This means almost that if each JFrame has it's own Window menu, the control object has to tell each JFrame when the contents change. Now I know there's an observable mechanism for this, and you can fire a change event, maybe it's as simple as whenever there's a change the control object iterates the list informing each JFrame to rebuild it's Window menu.

Phew could be messy with one object iterating the list and telling each to iterate at the same time. Needs thinking through. What we seem to be coming to is multiple identical lists and any change registered with the control object, requiring the request to be forwarded to each open JFrame, except the one that sent it in?!? More of a pub/sub thing maybe, like guys here's a change, and the JFrames listening for that change. Probably what observable does. This is all getting complicated, and observable collection, which each JFrame registers an interest in, and thus each JFrame implementing the change to its own collection, then regenerating it's Window JMenu.

Given a JMenu can't be shared between multiple JMenuBars I'm struggling with other options. Seems like a lot of work for something very common, e.g. internal frames under a jframe must have a way of maintaining lists or the Window menu - going to go look at some examples.

Menus sorted, I think!

Well they seem sorted for now. I have my main control object, which owns the list of running editors, and is responsible for building a common Window JMenu for all editors. Theory seems to be working ok, I could do away with the JFrame the control object has, as it's really only there at the moment to do a File->New and then off we go - that could get called from within the constructor or main() once the control object is up and running.

Going to explore collections next, i.e. whats the best Java constructs for keeping a list of open windows etc. At the moment I'm thinking when we launch a new editor we give it an index number which it supplies whenever calling back to the control object when e.g. it changes open filename, or closes down, so we can housekeep the window JMenu.

Sunday, 10 January 2010

Then it occurs to me ....

Maybe you can have each editor object, with it's own window, menus etc, and if New is selected, create a whole new editor and register it in the main "list of windows", that the Window menu consults? Dunno, gonna go play with some code to see what works, because that could work for MS Windows O/S too.

Sigh, it's not clear or obvious, until it's clear and obvious!

Saturday, 2 January 2010

The first JFrame and beyond ....

More reading reveals that the right way to do this for a Mac, is to create a main window which the menus are attached to. It then sits there as almost a main control window, so when a new score editor is created it gets added to the list of windows the app has open, so they get listed in a Window menu.

That main window though doesn't really have any content, we'd want the new score editor windows to be JFrames in their own right so they can operate independently. Where does that leave us with menus though? I can see with this concept of a main control frame, it owns the top level menu for a mac, and so things like File->New, Open and Quit, Window, Help etc all get managed via code in the associated class.

But each separate score editor window needs to have code which owns the Edit, Save etc menu items, ie the ones which impact the score itself. I know you can switch the code that gets executed from a menu when a window comes in context, maybe thats the way to do this, but thats menus for that JFrame, how does this work on a Mac where the menus belong to the main control window. Maybe it's irrelevant, and the whole menu comes in to context but inheritance means it can let the parent window handle the main control stuff and override the ones it wants. Bet there's a posh name for that in Java / OOP.

So perhaps the constructor for the main editor class builds the required system menus but the class for the actual score editors extend the main editor class and override the constructor, "knowing" the parent object will handle the main menu stuff. Hey I know what I mean!!

So you end up with JFrame derived object which is the main control window and it has many child windows, which are also JFrame derived, because you want them all to be operate almost independantly, ie so you can line them up against each other on the screen.

Maybe there's something other than a JFrame thats the right way to do this. Need to check. In the meantime there's no harm in cracking on and getting this up and running. Should even be OK on MS Windows I think, in that case the menus will just be in each JFrame.

It does leave us with this master JFrame, to which menus are supposedly attached which is just a window doing nothing. Maybe by not making it visible we can get over that but I doubt the menus will be shown at the top of the screen if the frame isn't visible. Hey maybe it doesn't need to be a JFrame, it just has code that is run by the concept of the main control objects menus, but they get run in the context of the child objects, which are JFrames. Problem with that is there might not be any open windows but the app should still run, ie the way the Mac apps work. Maybe I just say when we start up we create a New blank editor window, and if we ever end up with no windows open you just close the app? Not very Mac.

It feels like investigating having the main control process being a somehow non-intrusive or invisible window, ie just a menu - won't work on other platforms though - boo!

OK maybe I just build the app from the perspective of getting the editor class working, and worry about the wrapping later? Nah, can't put it off, it's too central to the whole notion of the thing. More reading and research I think as I still don't really get how to make this all hang together.