Icons in Menus

AmigaOS users can make feature requests in this forum.
User avatar
gonegahgah
Posts: 43
Joined: Fri May 31, 2013 4:22 pm

Re: Icons in Menus

Post by gonegahgah »

I should perhaps mention the purpose of having a zoneclass and a moveclass.
I guess this area of the forum isn't too bad to discuss these things in as they were features that I wanted to see in the Amiga OS.

The pointer.zone I talked about was a simple example. The OS itself already supplies drop zones that allow us to drop files into applications.
The zoneclass and moveclass are a more generalised approach to these things; with - as I say - zone locking to ensure applications are talking to valid zones.

The zoneclass is the basis for providing areas that are interested to know when the mouse pointer is over them.
So, they are similar to drop zones in this respect, but just broader in intent.

Hence you can have zones that will change the pointer when the mouse is over them...
But, you can also have zones within applications or across applications.

This is where moveclass also comes in. The moveclass is the basis for allowing things that want to follow the movement of the mouse pointer.
Present things that come to mind are Workbench icon dragging.
But again, the intent of moveclass is to broaden this feature...

For example, in tandem with zoneclass derived classes, this was to allow objects to be dragged - not just from Workbench - but across applications.
So for example you could click on an object and move the pointer away. The object would then become a move object and follow the pointer.
You could then drag it to a zone (well drop zone but not the current type) and let it go.
It could even be automatically grabbed if desired. Like feeding the kitty...
That is one of the pleasures of generalising to allow different implementations...

I was even working on - though I didn't complete it - moving objects across public screens. That would be very Amiga-esque.
This was going to involve remapping the imagery across the boundary to maintain some sort of colour correctness where possible.

So zoneclass and moveclass really go hand in hand.
One is interested in the mouse being over them and the other is interested in following the mouse where it goes.
Though they can have uses on their own too.
You could use moveclass to write the 'eyes' novelty program or similar things (so no zones involved).
And I've already spoken about pointer.zone which uses zoneclass only (so no movers involved).

I was also looking at more complicated issues such as providing ways to discern if an object being moved/dropped is one that an application is interested in.
I was working on that, I recall, so it will be interesting to rediscover what I was doing...
For example, if you drag something from an application's lister then that might be app specific and other apps might not be interested.
But there may be things that you want to share between certain applications...

I did find that having direct access to the Intuition would have made some things perhaps more do-able.
Moving icons would be easier, and non-blocking, if they could be done as little planes instead of directly into the screen.
But the Amiga OS only had window type planes - are they called planes; I forget?
If you have your pointer over the top plane then the mouse can't talk to the planes underneath.

So one of the things I think we need are planes that can go over the top but that don't form part of identifying which plane the pointer is over.
Let's call them moving planes...
Not knowing yet what has been re-done with OS4 I wonder if mouse invisible planes are somehow already present? That would be nice!
User avatar
gonegahgah
Posts: 43
Joined: Fri May 31, 2013 4:22 pm

Re: Icons in Menus

Post by gonegahgah »

There were a few different features I was working upon with my menu system.

One of the things I was working on was to make them live.
I suspect the way to do this - and that I probably was doing - was to create agents between the app and the menu system that could keep the information current.
If you rely on the application directly then you have to wait until it is ready to respond; that can introduce concurrency issues.
So I suspect I was going the way of using agents to offload this from the application.

Why would we want live menus?
It has to do with an Amiga feature and that is the ability to select menu items while holding the menu open.
This was done by holding the left mouse button while clicking with the right.
Can be a bit of a juggle but it is a nice feature and one that I wanted to support and to do so intuitively...

As part of this concurrency, and also providing user menu re-organisation, I was making the move away from using the Amiga menu system's mutual exclusion flags.
When writing an application it was possible for the developer to confine mutually exclusive (or radio button) items to the same menu or submenu.
But, by allowing users to put items where they want, mutually exclusive items can appear in different submenus.

So if you use 'menu holding' to click an item in one submenu then move to another submenu with an item mutually exclusive to it then it won't reflect the current state.
If they are in the same submenu Intuition automatically updates them for you; but not across submenus. That is presently up to the application.
Why would you want mutually exclusive items in different menus?
As I say, it's not up to me. With customisable menus it becomes up to the user. And I want to keep things live so the menus need to reflect the current desired state.

Maintaining a live desired state is not just something for radio buttons; though that is usually the most visible.
There are other areas of the menus that might not reflect the current state.
You can see a little bit of this with the "menus" example app in the SDK under Examples/ReAction/os4examples/Menus/Intuition.
If you hold the menu and go into 'Prefs' you can see: 3 check items, 3 radio items, a sub-item and an ordinary item.
If you click on the radio items - while holding - they mutually change live before your eyes.
However if you click the 'use radio buttons' to unchecked - while holding - the radio buttons remain accessible; even though you've said to make them inaccessible.
If you let go the menu and reopen the menu it is only then that they become inaccessible; because the application has had to intervene and make them so.

So one of the features I was working on was to make this all live via co-operative agents; leaving the application to not have to directly maintain the menu state.
There are other features that I'll mention as we go...

Soon I hope to convert my zones and movers over to OS4; once I work out how to code disk residing classes for the OS.
Talk is cheap; actions speak louder...
User avatar
trixie
Posts: 409
Joined: Thu Jun 30, 2011 2:54 pm
Location: Czech Republic

Re: Icons in Menus

Post by trixie »

@gonegahgah
The OS itself already supplies drop zones that allow us to drop files into applications.
The zoneclass and moveclass are a more generalised approach to these things
Sadly, the current drop zones are extremely limited. They are not implemented within a general GUI-programming framework; rather, they are a feature of the Workbench Library that is related to the AppWindow functionality. As such, they inherit certain features from old times: for example, they are unaware of layouting. If you install a drop zone, the zone's dimensions are fixed and you have to implement your own mechanism to re-establish the drop zone each time your GUI changes size. This is very awkward. Also, BOOPSI-based GUIs have no way to define drop zones other than resort to the Workbench Library functions - whereas ideally the zones should be set and managed at the OO level.

So your reimplemention of the zone functionality is not only interesting but also much needed.
The Rear Window blog

AmigaOne X5000 @ 2GHz / 4GB RAM / Radeon RX 560 / ESI Juli@ / AmigaOS 4.1 Final Edition
SAM440ep-flex @ 667MHz / 1GB RAM / Radeon 9250 / AmigaOS 4.1 Final Edition
User avatar
gonegahgah
Posts: 43
Joined: Fri May 31, 2013 4:22 pm

Re: Icons in Menus

Post by gonegahgah »

@trixie
Sadly, the current drop zones are extremely limited. They are not implemented within a general GUI-programming framework; rather, they are a feature of the Workbench Library that is related to the AppWindow functionality. As such, they inherit certain features from old times: for example, they are unaware of layouting. If you install a drop zone, the zone's dimensions are fixed and you have to implement your own mechanism to re-establish the drop zone each time your GUI changes size. This is very awkward.
By co-incidence, I just happened to be looking a this very thing in my old code. It seems my "zone.class" uses a pointer to the bounds instead of keeping those values itself.
This allows it to utilise the bounds of the subclass or superclass object itself without needing to be told of the bounds separately and in duplication. So this does automatically handle layout changes that occur.

For example, I originally wrote a simple "windowclass" of my own. I then made a new class called "window.zone" that in the main just adapts a "zone.class" on top of a "zone.window".
The adapted "zone.class" then utilises the windows bounds to help the MouseZone commodity know if the pointer is within the window's bounds before asking the window if the mouse is truly over it.
Afterall, windows don't have to be rectangular. The "imageclass" and "gadgetclass" based zones can do exactly the same thing.
The simple test example - I am rewriting - doesn't use gadgets or images at all and instead uses "complement.zone" to complement the rectangle area when the mouse is over that area.

Hmm, just thinking about it now a couple of things occur to me.
Why not just get a pointer to the bounds directly instead of storing a pointer to the bounds as well?
I'm also wondering if I can utilise this to make some layers that are invisible to the mouse for the purposes of zones?
I'll have to think about this...

Speaking of the "window.class" - a bit prophetically perhaps; though to be expected - I mentioned in my code the intent to use a "windowclass" that would hopefully be developed by the OS team.
With respect to this, I should hopefully be able to use adaption to adapt my "zone.class" over the top of the OS4 "window.class" - instead of mine - to make the "zone.window" class.
Adaption comes in useful as it allows multiple inheritance to be applied and I don't have to rewrite the zone.class code.
Maybe the "zone.window" features will be directly incorporated into "window.class" one day; though that wouldn't be necessary.
Also, BOOPSI-based GUIs have no way to define drop zones other than resort to the Workbench Library functions - whereas ideally the zones should be set and managed at the OO level.
So your reimplemention of the zone functionality is not only interesting but also much needed.
Thanks. I also realised, redoing my code, that drop zones are just a sub-category of zones. There are varieties that aren't drop zones too. Hopefully this will broaden out the possibilities...
User avatar
gonegahgah
Posts: 43
Joined: Fri May 31, 2013 4:22 pm

Re: Icons in Menus

Post by gonegahgah »

Slowly but surely things start to make sense again.
Shows a deficiency in my documenting I think... I will improve that now.

I was trying to work out why my MouseZone wasn't actually making any zones go active with ZM_GOACTIVE.
Instead all it was sending out was ZM_HANDLEINPUT as well as ZM_GOINACTIVE.

There's a bit of a co-operation thing going on between MouseZone, window.zone, group.zone, and the miscellaneous zones as well as movers when I get to them.
Reflecting on my code, I may be able to make the movers be invisible zones afterall. I'll be interested to see if some particular mover objects still work under OS4...

The reason MouseZone wasn't sending out GOACTIVE was because it talks to window.zones and window.zones are the middle-person.
It is the zones within the windows that need to be told to go active, and it is the window.zone that looks after telling them to go active.
I'll review that implementation after I get it up and running under OS4 but at least I know now what I was doing and it was probably correct afterall.

I had forgotten that my window.zone was built upon group.zone and adapted on top of windowclass. ie. window.zone--group.zone--zone.class--windowclass--(rootclass I guess).
There may even be a "listclass" in there somewhere. I'll have to check. That's what I like about class adaption.
A group.zone like groupgclass provides a means of grouping multiple zones together - though I'll have to check out if it is for exactly the same purpose as for groupgclass.
I imagine it does and that I've polymorphed the window.zone so that it concerns itself with individual zones in its group list.

As I said prior, zones don't have to be gadgets or images, though they can be. So, as they are separate, they need to form their own grouping in a window.
So you can end up with a gadget list, a zone list, and you can plonk your own images where you like. And some of these can happily be in these distinct lists all at once.
User avatar
gonegahgah
Posts: 43
Joined: Fri May 31, 2013 4:22 pm

Re: Icons in Menus

Post by gonegahgah »

When looking through my MouseZone code and zone.class code I was left wondering a few things:
- I am presently using a public semaphore but, after it was suggested to me, I wondered if I can just use a mutex and do so by common access through the zoneclass.
- Also, I'm using things like a Window pointer and Screen pointer in my Zone messages but now I wonder if I shouldn't just use a GadgetInfo like the gadget methods send.
I have afterall noticed that there are many similarities between zoneclass and gadgetclass.

I won't worry about these initially and will just rewrite my code as it is for the moment making it work for OS4.
I'll try out these changes after my first few zones are working in OS4.
Another thing I realised was that I had written MouseZone because I don't - obviously - have access to the Amiga OS code itself.
I am hoping this implementation will be incorporated hopefully into Intuition itself...

I was also trying to remember how target zones (ie. drop zones and gobblers) are supposed know if a mover is something that they were interested in...
It finally occurred to me, what my answer had been, while I was driving home...
Ideally, what you don't want is for a target zone to have to determine if a mover relates to it while in the input event process.
Fortunately, the way around this is that when a mover begins its journey it tells the list of participants that are interested in a particular type that that type is on the move.
The mover afterall already knows what type it is moving; makes sense.
That way the target zones can be ready to respond in the affirmative when they are asked to go active, after which they then wait for the mouse button to release the type over them.
A gobbler (which doesn't wait for the mouse button to release) however will eat the type and go inactive straight away.

Making a list of interested participants for a particular type should be fairly easy to implement.

What this means is that the process of dragging and dropping can be done for a range of different types without an artificial register of types (that then becomes difficult to maintain).
You also remove the recognition process from the input event process which keeps things ticking along nicely.
I can't remember 100% the specifics but I know it was something like this. I'll find out as I continue...
User avatar
gonegahgah
Posts: 43
Joined: Fri May 31, 2013 4:22 pm

Re: Icons in Menus & zone.class

Post by gonegahgah »

When I was looking through my old code I noticed there seemed to be a mismatch between a small library that I wrote and the source files I had written.
It turned out the source files were older versions.

I wanted to look at my - I think it is the one - hard drive I used back then to see if I could find my latest source files for it.
But, I've had no luck so far seeing the contents of the old hard drive. So instead, I set about recreating my code.

As is the way with these thing, in the process of trying to recreate, I could now see ways to improve this, so that is what I did.
I've meant to initially just convert things straight across so I can see them working under OS4. But I had to recreate this code now so...
The library code is not code that really relates to the zone.class and move.class implementations - except the class adaption at some point.

Anyhow, so I'm back to looking at my zone.class and move.class code.
Thanks to a helping hand I have been able to see ways to improve upon that as well.
As I say, I'll just do a straight convert first but then I hope to make these improvements as well.

One of the improvements should be to move the Zone public semaphore into the zone.class itself and use a mutex instead.
I think the suggestion to use a mutex instead of a semaphore will be a good one.

Also, I should be able to move the watcher handling into the move.class itself and out of MouseZone.
That way, to add an object to the watcher list (icons, marquees, drag items, sliders, dials) you only need to ask the move.class sub-class to add your object.
Having the watcher list in the classbase data allows this to be shared just as the mutex is shared by having it in the zone.class classbase data.
This is a really nice way to make things public; by using the BOOPSI classes themselves.

These are the reasons then that we have the zone.class and move.class.
That is to allow other objects to participate in the zone tree and the move chain by a simple mechanism.
Building classes on top of zone.class and move.class nicely provide these features (or at least I think so).

But what are these watchers? Watchers are simply objects that follow the movement of the mouse.
A move.class for example can be added to the watcher list so that it can move around with the pointer.
The "eyes" program is another example of a Watcher that could just sit in the watcher chain allowing its 'eyes' to follow the mouse.

It is a chain so that several things can register an interest in watching the mouse at one time.
Movers will usually be added to the chain while they are moving and be removed once they are finished with.
You can also use group.move to allow several objects to be moved at once. I haven't tested that but I imagine this will work.
I like the suggestion in another thread about >10 icons being compacted to a 'icon group' drag icon.

As I mentioned, I would like this to provide a generalised mechanism for all hovering and dragging needs for OS4 and applications written for it.
Hopefully it will prove useful and useable for that purpose.
User avatar
gonegahgah
Posts: 43
Joined: Fri May 31, 2013 4:22 pm

Re: Icons in Menus

Post by gonegahgah »

I've been puzzling over my implementation. I couldn't understand why I was delaying the rendering.
Now it starts to make sense to me again but I think I will implement it slightly differently.
I might even add comments so I can recall what I was doing.
Very sloppy programming!

I think the intent was to allow multiple objects to be added to the Watcher list and do all pre-calculation before going through the list and rendering those that indicated they wanted to.
Now I'm thinking that the group.move and similar will be better way to handle this.
Certainly allowing the group to pre-calculate its sub-items and then re-render them all at once makes some sense to reduce a cascade effect; though computers are a lot faster these days too.
Certainly, the objects can return that they wish to render ie ZMR_POSTRENDER.
The post ZM_RENDER method can then also return ZMR_KEEPHANDLING if the watching is to continue.

So that removes one loop. I'll do that straight away as it should be an easy fix.

I also had a Watcher chain for while IBase was locked and another Watcher chain for after IBase was unlocked.
I had assumed it would be necessary for AutoPoint to operate while the IBase was locked but I never tested this out.
I was working on my menu editor while the A4000 was still working so AutoPoint seemed like a lower priority.
Samual Crow correctly pointed out to me that you can't activate Windows - or do very much of anything - while IBase is locked.

So that removes that first pair of loops I had inside the locked IBase. I'll remove them straight away as I hadn't used them yet anyway.

That should make the whole operation a lot cleaner.

Importantly this still leaves the Zone lock.
This ensures Zones remain in existence while they are being interrogated.
Doesn't help old windows which will still be able to possibly cause problems for AutoPoint by closing while AutoPoint is using their pointer.

Zone based windows won't have that problem and AutoPoint will be able to Activate them without ever causing any problems.
It will also be useful to make it so that the Zones lock is obtained before attempting to close a public screen.
In this way the public screen will remain while it is being examined and will then close when the brief examination ceases.

Also, it is nice to see the interplay between all the elements.
The move.class actually has zone.class as its superclass.
This is so that move.class can access the shared Zones lock.
This was the case in my existing implementation and will be still the same once I move the lock from presently being in a public semaphore and put it in the classbase structure for zone.class.

If you need to access the Zones lock - for example to ensure no-one is examining the screen, it's windows and it's zones - you simply create a zone.class object I think.
More sensibly you should be able to open and call the zone.class directly without even creating an object.
I'm not sure how I have done it presently so I will have to check. I can't even recall off the top of my head if it is possible to call BOOPSI classes directly.
You obviously do when you use NewObject() because the object doesn't exist yet! So I imagine it was possible?

So, although movers aren't really zones they both share the zone.class. It's nice when a base class actually serves a purpose.
Ergo for the move.class which allows movers to be added to the watcher list which it also holds in it's classbase structure; or at least it will.
I should be able to make these base classes have zero size instance data if I haven't already...
Presently, I think I have the Watcher list in the Zones lock; but I don't think it needs to be there anymore.

Sorry, in my last post I was getting my subclasses and my superclasses mixed up.
Post Reply