Sunday, 19 December 2010

Falling into place

It's starting to feel like a real application now. I have the layering of components right I think, keyboard focus moving as needed, mouse listeners behaving as they should for their components, menus and actions coming together. Still got to get popup menus happening and making the menus on the menubar context-sensitive, i.e. disabling or even hiding entries not appropriate for the current context.

The drawing components are all resizable, and drag and droppable, although I still have reservations about Java in the space, the DnD interface seems out of place. Also started doing some of the development on a linux vm, having started on Mac OS X. Some differing behaviours which will need sorting at some point but I don't see linux as a tier 1 target OS. Most drummers will be Windows or Mac.

Time to review the to-do list .....

Saturday, 20 November 2010

So Java is rubbish for printing

Especially on linux and Mac - and also Windows! Or maybe I'm missing the point. I can print portrait, on all 3 platforms. Trying to go landscape has Mac OS and Linux with the paper rotated but not the drawing, on Windows the whole damn thing is rotated so it looks like portrait but on its side!

I give in!! I will come back to printing later.

Now I'm at the stage I need to write an equivalent of JTextComponent and all the gubbins that surrounds it but for musical notes (well drumming ones anyway) instead of text. I've taken a look at the source code of JTextComponent and the accompanying docs and examples - there's no way I should just subclass it and use embedded components in a StyledDocument. There's just too much to get in the way. Also making the notes into a Font, with glyphs etc for the drawing strokes. Just not flexible enough.

Only one thing for it, an industrial strength JNote class and JScoreComponent, Editor, Pane etc.

One of the big things is this is a drawing program at heart, each note will be placed exactly where the author wants it, not some predetermined space from the previous one. The option exists to write a program which behaves that way, which could in fact be easier for some authors, but the one we're writing here gives all the decisions to the user.

Wish me luck - that bloody printing does bother me but it appears to be a bug in Java.

Tuesday, 9 November 2010

Papering over the cracks

PageFormat, Paper: bah! Slowing down here thanks to my lack of grasp of the printing system. OK so double precision co-ordinates throughout thanks to G2D - need to work that back into the screen co-ords handling but portrait and landscape are throwing me atm. So the user selects landscape, I should just pass the PageFormat to print() and that should be it but no, something screwy going on with the Imageable co-ordinates being wildly out when landscape, especially weird when there's no borders on the paper / printer combo. More severe looking at required!

Saturday, 6 November 2010

Keep it standard pays

The todo list is now vastly reduced for this first baseline app. Going to skip snap to grid for now, the AWT DnD implementation is now becoming a restriction in terms of snap to grid and zoom using AffineTransform. Will implement the rest of the app and ponder hard rewriting the DnD implementation. So still to do:

  • create ability to constrain the component resizing to certain directions only
  • create ability to always retain aspect ratio when resizing a component
  • implement image resizing within image component (retaining aspect ratio)
  • allow drop of images from external sources
  • implement paper size metrics etc, borders / gutter et
  • implement export action, with pdf initially as only target, maybe png too?
  • implement app preferences handling, saving to user dir etc (paper type, fonts blah)
  • implement splashscreen on startup
  • figure out packaging, e.g. jar, mac app etc

Friday, 5 November 2010

Design for drag image

Well had implemented the drag image as supported by DnD but ...
It doesn't work on Windows, and ...
It doesn't allow you to snap to grid on the drop target, essentially as the drop target can't get hold of the image or alter it's location in any way. It may be possible to do the following:
When the drag operation enters a component which has registered itself as a drop target and listener, dragEnter can extract the transferable, get the transfer data, instantiate the object, grab the drag image from it (as thats implemented in my source component), store that ghosted image in the target component, and then as dragMove is called (or whatever the motion listener is), it can paint the image. When dragExit is called it nulls the ghost image and we're back to square 1.
Must remember to null the ghost on successful drop.
This way the overheads of creating the image only happen when the cursor enters the component, not on every move.

Thursday, 4 November 2010

Coding, coding, coding

Implemented the first few requirements from previous post. Got the borders sorted on the PageLevelComponents and the menus etc to toggle to a page layout mode. Decided to make resizable components visible when in page layout mode - they disappear when user goes back to note editing mode.

Implemented the drag images too, shame the JVM on Microsoft Windows doesn't support them! There are workarounds out there using the glass pane etc, more code and a platform specific code branch required so ignored for now. Went seriously down a number of ratholes with that before!

Friday, 29 October 2010

and this means I need to do what exactly!

I have to document this here, otherwise I lose track of all the todos and tasks in the code - must look at eclipse task management stuff one day.

Next steps:

  • refactor component names to be PageLevelComponent (for ease of reading)
  • implement drag lock switch in the page level component
  • implement menu to toggle page layout mode (View -> Page Layout maybe)
  • implement border highlighting on main view panel when in page layout mode
  • implement snap to grid for page level components when in page layout mode
  • implement page level component border visibility based on mouse enter / leave when in layout mode
  • create ability to constrain the component resizing to certain directions only
  • create ability to always retain aspect ratio when resizing a component
  • implement image resizing within image component (retaining aspect ratio)
  • allow drop of images from external sources
  • get default serialization working for a score (save/restore the view)
  • get File -> New / Open, Save, Save As ..., Close menu actions working
  • implement drag images when DnDing, or at least the right size rectangle
  • figure out DnD cursors, only works on copy rather than move at the mo'
  • implement paper size metrics etc, borders / gutter etc
  • get a print infrastructure working (delivers PDF out of the box on a Mac)
  • implement export action, with pdf initially as only target, maybe png too?
  • implement app preferences handling, saving to user dir etc (paper type, fonts blah)
  • implement splashscreen on startup
  • figure out packaging, e.g. jar, mac app etc
Enough to be getting on with? Should mean the whole app infrastructure is in place up to the page level components. What's left after that is the interesting musical notation bits, which, when it comes down to it, is when we will have something beyond the extensible doc handling app the above should deliver.

Pause for breath

Reworked the code for the abstract base class that sits under the page level components, i.e. the text, image and score line widgets. Having taken reference from many different examples it needed harmonising a bit. Bottom line is I now have a component which sits in a JPanel which is DnD draggable and can be resized by the user. Still lots to do though and I stopped to think through how the mouse interactions were all going to work.

At the page level you want to be able to move those components around and drop new graphics or text in but you don't want them moving when you're manipulating the individual note elements, either dragging them about or creating a selection of a group of notes with the mouse by dragging a selection rectangle across the page. If the component which represents the score line is draggable then clicking and dragging within it's bounds would mean picking it up and moving it rather than drawing a selection rectangle - and how would the code tell the difference? Maybe the user was dragging the line about!

I thought of a couple of ways of approaching this. Firstly I thought we could set an "anchor" property on the line so that it locks it in place thus interpreting any mouse drags as select attempts This would be achieve by having a border which became visible when the mouse entered the component area which would hold the lock / anchor icon. User can then "unlock" the component and move it about, then lock when finished. OK, could work, bit of a funny sort of paradigm for a drummer to have to learn.

Next thought was to create the ability to lock all page level components. This could be achieved by menu action, or properties dialog of some sort. The paradigm then becomes "OK lay out titles, authors etc and any graphic logos etc, plus all the lines you want on the page then exit page layout mode and go into score editing mode" or words to that effect. I think that seems easier from a user perspective, i.e. consciously take an action to lay out the bits and pieces then switch to doing the score content itself.

I'm going to code up the latter one I think. Should be a case of setting a property in each page level component (of which there won't be too many) whenever the menu selection is made to switch modes. Could even put a special border or something round the page if in layout mode so it's easy to see.

Further thoughts included snap to grid functionality, i.e. when in page layout mode there's a faded grid in the background to which all component align themselves as they are being dragged (or more accurately as drop zones are tested by DnD). Could be interesting to figure out if that's something best implemented using a custom layout manager or if the components become aware of their position relative to the parent panels grid lines, i.e. code it up in the drop test function.

The component abstract class is becoming quite complex having to implement all the DnD interfaces, plus mouse handling and clipboard etc. Jeez not even gone anywhere near copy and paste yet! Or keyboard interface!

Am probably thinking ahead too much but the note elements could be implemented in the same way as Docs are in the swing text components ..... needs research as I've not really done anything with those components before, just read how they work.

Should probably post some of the component code up here to show how I've managed to make this work, seems to be a common problem on the forums. One thing I have had to stick on the backburner is zooming the view - turns out using AffineTransform is really easy to implement the scaling but you can't invert the scaling for mouse handling in the Swing DnD system - there's just been no thought put into that in the design of DnD or if there has, it's not apparent to anybody out there. Plan B is to iterate all components and apply resize ratios on zoom - expensive task in capacity terms as it's a piece of batch work that needs to complete before the user has a perspective again - think this is going to be one of those heavy GUIs when finished! Or at least until someone discovers how to make scaling a point and paint pastime ...

Anyway if anybody reads this stuff, and wants to see the code please just ask so in the comments.

Sunday, 17 October 2010


So the approach of start again in a streamlined way has really worked. Storing everything in objects derived from Swing components is working, we have the main panel up and running, can do text based objects, jpegs and other panels, although the panel within panel piece is going to take some time. It will represent the line on which notes and bars are stored, so it's a container, needs to be dragged around, it's a drop target, needs to be resizable, phew!!

Head down time ....

Friday, 8 October 2010

Dragging and Dropping

Cooking with gas now I think. Just implemented Java DnD in the template GUI app. Glad I wrote one of those as it's easier to model and try new techniques in something thats lightweight compared to the drumscore code. In fact, what's becoming obvious as I model ways of doing things is I can simplify the original code now I understand better how to use the facilities of Java and Swing. I'm not feeling very charitable toward the original code I was using as inspiration as it avoided using many of the native features and tried to slavishly follow MVC when Java / Swing doesn't lend itself to that paradigm.

I can feel some slashing and cutting through the drumscore code soon to grossly simplify. And I must stop getting distracted by trying to Apple Mac everything - must stick to the discipline that says write the basic app then add the bells and whistles. Discipline? Huh!!

Monday, 4 October 2010

Click! Eureka! Boom!

Sometimes it just happens like that. Not through any form of higher advantage, but it simply just comes together. In this case I believe it's come together as a result of the journey, of hand cranking attempts to implement function, not quite knowing how it all works, taking it to a serious level of frustration and detail. Then take a break. How many times has it happened for me like that - dive in deep, take a break, come back to it and with the right focus it falls into place.

I can now see end to end how to implement the software I want. I can now say I see how Swing can meet the needs of the gui I want to write, and without going off piste.

It's a recipe involving no layout manager (absolute positioning), JLabels as the the container for text items and with custom painting they can host the notes and other elements too. JPanels can host the lines, or bars or however I want represent them. Swing Drag and Drop with custom dataFlavors will implement most of the drawing needs.

One last little bit, perhaps even the desire to store in XML can be handled to through XMLEncoder although I have to figure out the Beans stuff first before design can seriously get under way.

Think I'll freeze the code I've built so far, and start a new project from scratch using the lessons learned and perhaps even reusing some of the better code from the trials and tribulations to date.

Happy days

Sunday, 3 October 2010

And we're off again

Good progress, removed the control window stuff and turned that into a form of application controller object for all the stuff that needs to be maintained centrally. Also added code to cascade new windows and add a serial number to each new window as per style guides.

Seemed to get up to speed fairly quickly with the app, the overall structure of it and it's all a bit more familiar than when starting it up 9 or 10 months back.

Next is the widgets in the document, need to get a strong framework for them in place

Saturday, 25 September 2010

Creak, groan, click

are the noises made as one drags oneself out of 6 months of coding slothville :) Well not really as I've been coding in some proprietary languages some statistical automated trading strategies. Great fun, if not immediately profitable!

So another winter looms, and I've started thinking about dusting off this project, I mean, it's only been something I've been thinking about for ten years or more, so what's another 6 months? Been thinking I'd like to lose some of the fat that's in the code so far, stuff that's there because I wasn't sure of the right design pattern when initially learning all that's needed for a java based music notation gui. Things like the concept of the master or control window - just not needed, if there's no drawing windows open then exit the app, when we start up, if no arg1 with a filename, then new manuscript please.

Am sure it will take me a few weeks to get back up to speed, does eclipse even work still? Probably a few new versions to upgrade to.

Tuesday, 13 April 2010

Squashed a bug

As I add functionality, it exposes bugs in the code I started with. For example the attributes dialog for a text item was good, the implementation was tested, however it highlighted the way I was changing text attributes by using deriveFont was flawed, as it remembers the attributes from before.
Implemented the right click menu infrastructure in the software, looking good, so started writing actions, starting with one to create a new text item. Was interesting as I wasn't sure how I was going to do it from a menu item as I couldn't answer the question "how do I know where it's location should be on the page". Answer was implement a first-click infrastructure by storing an action away in the mousecontroller to execute, ie user says Insert Text, mouse cursor becomes a crosshair, next click causes configure dialog for a new text item to show at that point. Simples - I expect more bugs from this later as it gets exploited more!!

Friday, 9 April 2010

Coming together

Abandoned my hand-crafting of zooming the view when my knowledge levels got sufficiently high to understand AffineTransform. Now all the drawing bigger or smaller is handled by the graphics library. Some tricky bits around scaling the drawing canvas and margins etc but all done now.

Things on the to-do radar include:
  • configure text item dialog box (bold, underline etc)
  • pop-up menus (right click)
  • more work around constraining movement of text adornments, still "sticky" in places
  • file open / save dialogs and code (will we use xml as the format????)
  • new score dialog, let's discuss!
Currently a new score is created blank with only one feature - the title text adornment. Question is do we want the user to manually insert staff lines or an initial dialog which lays out the number requested? My opinion is we code up context sensitive menus which allow insertion of new bar lines. The Insert menu item can be created for the top level menu too, inserting a new staff line at the start of the list if empty or before the current active staff line, i.e. the insert point is before the current object.

You'd expect a replace functionality too, ie if a whole staff line was selected, then a new one would replace it. Not sure that's important as you're unlikely to want to lose the contents of an existing selected staff line. Must go and look at my music theory notes too as I want to get the names right.

Also prominent by omission is the ability to choose portrait or landscape. That's just a code it up issue, i.e. if it's one and you want to go to the other do you shrink / stretch spacing between notes as appropriate? Probably not that many lines of code but it's going on the laterz list.

Saturday, 3 April 2010

Preferences version 1

Simple dialog box now in place, got tied up trying to replicate the look and feel of the pref dlg in Eclipse, confusing my inner being with GridBagLayout etc. Enough already!! Job is to get a working app going then prettify it.

Decided not to allow change of orientation at the moment as it raises too many questions and therefore probably lots of code! If you change the shape of the page then all the objects on it need realigning to fit within - code code code. So am going to do a New Score wizard dlg that asks this at creation time and that's it. So we're restricted to 1 page and get the orientation right at creation time. I wouldn't pay money for that.

Back to the main app now, dlg box for changing properties of a text widget can come later. I think I've decided the score graphic objects on the page will have their real world dimensions translated to logical page dimensions (using dots per inch) when they are loaded up so they are always stored in ready to use dimensions. Should take the overheads off zooming, moving etc. I really want to solve the moving problem I have at the moment where if the mouse moves too fast off page the last few moves aren't sent to the app. Perhaps making it quicker to process the moves will help. Certainly putting additional unit conversions on the critical path won't help.

So the only time real world units get used for say the distance between notes is when saving to disk, and of course converted back when read in. Let's see what that decision brings us!!

Wednesday, 17 March 2010

Lesiurely voyage of discovery

The more I work this application, the more I learn about the standard java classes, and the more I learn about the example application I've used as a muse till now. I now understand enough about the mouse interfaces and co-ordinates etc to see that the in the example, each drawing object had it's own mouse listeners, whereas I've implemented one for the whole view.

Given the number of graphic objects that will appear on the canvas the mouse listener interface would need to be very scalable indeed if there were several hundred listeners in one app! As it is I implement my own mechanisms to see if mouse gestures impact any of the widgets. Not sure what OOP purists would say but after the work put in, it stays my way for now. Drag and drop might be interesting though when I come to implement that.

Time for the apps first dialogue boxes I think. One for the preferences e.g.

  • Title
  • Orientation
  • Margins

The other is for the attributes of a text adornment:
  • Font family
  • Font name?
  • Size
  • Bold?
  • Italic?
  • Underline?
  • Alignment, right, left, centre - tricky - no code to handle that yet, maybe v2 ;-)

Tuesday, 16 March 2010

Guess who's back?

Managed to get some time this week to pick this project up again. Getting there! Now got zoom working for both the view and the mouse controller, a few gray areas for me cleared up but I'm storing info in the Model now because it needs to be referenced by the Controller and the View, even though you could argue the View is the thing that should be worried about coordinates etc. Anyway, in the past now, decisions made.

Working on getting proper bounds checking in place for when objects are moved about, i.e. setting the margins up and not moving an object outside those bounds. Tricky bit is the point at which the mouse is pressed is within the rectangle which defines the object, not the top left corner so lots of offset arithmetic which makes it all looks complicated, and confuddles my brain trying to work it all out. It will happen though.

Current question is by having each graphic item expose its boundary so the code which moves things around can decide whether it's a good thing or not to move it, is fine for adornments whose constraints are the edge of the margins. For notes etc, they will be constrained by bar alignment, so I suspect there'll be more rewriting coming up when those challenges reveal themselves!!

Wednesday, 10 February 2010

Freakin' text drawing stuff

It got tricky - trying to make the text component in the model aware of the rectangle it sits within for hit testing for mouse actions. Took time out to read the J2SE Graphics2D tutorials etc, some other stuff on the now Oracle / Sun site. There's AttributedStrings, there's TextLayouts, there's simple Font and drawString, but there's nothing that discusses the best widget to use.

I've gone for simple Font and draw, using FontMetrics to get the real estate it covers. Unfortunately every widget I've looked at needs to have the graphics object available which is only there it seems on the draw method - not sure how to get it any other time so am using the opportunity when draw() is called to update some statics about size, rectangles etc.

When a string is drawn the coords aren't the top left of the logical rectangle it occupies but at the bottom left of the first character, but not quite the bottom, there's Ascent, Descent and other stuff I need to get more familiar with but needless to say there's some more complexity going in to the object to cater for this and maintain the concept of a hit rectangle with other adornments, eg jpeg etc.

Nearly there ....

Monday, 8 February 2010

Working on the mouse actions design

Thinking the objects in the model need to store their selected state, and when it changes fire out so the view knows to redraw. The object needs to know how to draw itself in a selected state too, so the user can see it's selected.

Maybe we need a Set which allows the editor to quickly navigate through which objects are selected, e.g. if user clicks the mouse with the shift key down, then the object at the co-ords gets added to the Set, aswell as changing its state. Then any action triggered, through either menu or other means is applied to all items in the Set of selected objects.

This then allows moving a number of items together for example, or deleting them. If all the items are of the same type then maybe we can format them to eg same font or size - adds tricky stuff so maybe v2.

Saturday, 6 February 2010

Mouse moves

Getting the mouse motion and clicks into the app turned out to be quite easy in the end - as always, once you know how. Got to think through the details carefully now of which objects should handle which actions and how, carefully separating the roles of the model, view and controller.

Have to say my hearts not in it right now, head is swimming with other stuff so this may have to take a back seat again for a while. Will see if I can concentrate on thinking it through at least, as a distraction to focus on something other than whats floating around in the head right now, a little relief maybe!

Monday, 1 February 2010

Focus on adornments

Here's where I have to set some design in stone for v1.

So adornments are all the non-musical elements that make up a score, i.e. text strings the user might use for say the author, a copyright statement, the title, the setting (march, strathspey etc), name of the band written for, date. Approach is not to dictate any requirement except the title, you got to have one of those!

The storyboard for a new score is to create an empty A4 document, give it a title of Untitled, define a distance from top of page for staff line start, and create 8 staff lines in portrait mode and hand it over to the user. (V2 note: define header area, footer area and implement ability to create more than 1 page; implement choice of paper size)

So what can the user do next? Select File->Properties to set page orientation and number of staff lines on the page. Warn user if number of lines reduced and it would mean deleting a populated line. If user increases number of lines (more than 8? good luck) then they'll be appended at the end and all the lines proportionally spaced on the page, below the defined header space.

Now adornments - we've already created one - the title string, which is located at a default position. User needs to be able to move it, change fonts, bold, underline, italic and of course change the content. Also will need the capability to create a new one!

Moving an adornment
User selects the adornment by pressing and holding the (left) mouse button down. Next the mouse is moved (while still holding the button down), and the adornment follows, i.e. dragged to the new location, as determined by where it is, when the mouse button is released.

Changing the content of an adornment
User double-clicks the adornment, dialogue box opens.

Deleting an adornment
User selects the adornment with a single click (enables Cut menu item), hits delete, backspace or Ctrl-X as accelerator to Edit->Cut menu item
User right clicks adornment, triggers pop-up menu, include Cut, Delete menu items
No difference between Cut and Delete in V1
(V2 note: implement undo / redo and Copy, Paste capability)

Creating an adornment
Not sure what menu item this needs to be on, e.g. Insert->Label->Text
User right clicks mouse button, triggers pop-up menu with Insert->Label menu items
Not happy with this! Seems clunky. If the create is triggered by the mouse then we have the location to create the adornment. From the menu, we need to think of where we create it - if we default to say somewhere need top left, the next thing the user needs to do is move it.
The create action pops up a dialogue box appropriate to the adornment type.
Am only formally supporting text adornments in V1, will include a jpeg logo adornment with in V2 or before if it helps build the code framework for extensibility. (i.e. factory methods which select class to create at run time)

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.