I am developing an Widget for Eclipse RCP. I made a Shell, which I want to combine with Events (Resize, Move etc.) in a View, in which I have a Composite. How from the Composite point of View I can get it's View, in which this Composite is placed?
You can always call getParent() to get the parent control. If the composite you are interested in is not the direct parent, consider passing the control you want into the constructor, and keeping track of it that way.
Related
I am creating my own GUI in OpenTK.
I want to fire a mouse event when the cursor is, for example, in one of the GUI controls. How can I do that? Because now I'm just iterating through a list of items in the main class, and in the Opentk´s window´s MouseMove event I'm just checking if the mouse coordinates are within the "region" of the component I'm drawing.
This works for now, but I think it could be done in a better way. This way my code is unordered and in the main class, and I would rather have it in the specific component class.
What I would like is to have an event attached to each component of my GUI, so that I can define many events for one component.
I mean, I would like to have for example a button component where I can override or just use a method that fires when an event occurs. Same as OpenGL´s window where you can override events.
This is not a complete answer, because your question is quite broad, but I hope it helps.
In order to implement such a system, here are the core components for a potential design:
UI Components: Some kind of standard interface where different component types can define logic for interactions. Depending on the language, the most common approach is probably something like a parent class Component, with methods to be overridden. These would probably include things like:
Mouse Hover
Mouse Click (press / release)
Click drag
It will also likely need some additional associated information:
Some way to determine the component's location. Could be providing a bounding box, or perhaps a method that tests if a given point is within this component or not.
Information or functionality for drawing the component.
Display and layering settings (is it visible or hidden, should it draw on top of other components or behind).
UI Context: The context is a structure that defines the set of components that are existent in the UI. This could be something like a list structure of Components. In order to build your UI, you would add components to this context. The context will define some behaviour:
Managing components (add / remove / modify).
How to draw the entire context (for example, looping over each component and executing the draw functionality for each).
Handling of events (see next section)
Event Dispatch: To make your UI usable, you can insert an "adapter" layer that handles events from your windowing library (OpenTK) then translates them into usable events for your components and dispatches them. Here is an example of how this might work for a "click" event (pseudo-code):
function TK_Event_ClickPressed(point) {
for component in context {
if component.ContainsPoint(point) {
component.EventClickPressed()
}
}
}
This is actually the more tricky part of the design, in my opinion, because there are some tricky conventions around how component based UI works. You don't necessarily have to follow them, but they're important to be aware of at least because it is probably how people expect your UI to work:
After click press, click drag continues to occur until click release, even if the cursor leaves the component area.
"Actions" occur on click release.
Click release only takes action if the corresponding click press occurred on the same component.
The click release doesn't take any action if the cursor is no longer inside the component (leaving and re-entering the component before release still does the action, though).
You can only be actively clicking one component at a time (the one shown on top), even if multiple components overlap at that spot.
Assuming that you follow these conventions, this means that dispatching events is actually a bit more complicated than just checking if the event point was in a given component or not. You need to maintain some kind of state to keep track of whether the context is currently in a click or not, and which component, if any, is "consuming" the current click. That is, which component should be given the click release and drag events if they occur.
With these systems in place, you just need to create a window, create a UI context, register the adapter layer to the window to act on that context, set up the window to draw the context on frame, then use the context to add / remove / modify components in your program.
I want to build a simple forms designer in Cocoa and need to move controls around on a form using the mouse (click, hold, move around, release).
Do I need to inherit new classes from all control classes to intercept those events ? Is there a way to implement it generically for any control?
One way might be to have a single large custom view that fills all the space the controls will be in. Implement the necessary methods to implement mouse events in this view, doing hit detection on the control views and moving them around. This approach requires only 1 custom subclass of NSView, and you can use any views or controls you want to move around without subclassing them.
Write a custom view to contain the controls. Override -hitTest: to ignore the controls and return self instead. Then when you receive mouse events, figure out which control they apply to and move as appropriate.
I’ve been reading through several books on Mac development, but cannot find the information I’m looking for.
The books all describe how to make floating windows or panes, but never mention how to make them all in one window. A simplified example of what I’m looking to create is shown below:
Basically, there will be three windows; A selector window with radio buttons to choose which NSDocument is currently being used, a window underneath that with buttons that show different windows to the right that allow viewing and manipulation of certain data.
For a example, each NSDocument may have a color value that can be set in the window shown by clicking view A, and some text strings that can be set in the window shown by clicking view B.
So the questions are:
Is it appropriate to use a single NSDocument sub-class for each Doc #1 and Doc #2?
Which classes should I use to set up the application as shown? NSWindowController? NSWindow? NSPanel?
I’m only looking for guidance on what to read up on, so any pointers are appreciated.
EDIT:
To clarify this further, I want to have a table view where the buttons are (View A & B), and by clicking them they will cause the other window/view to change it's contents.
It's like the split view in the iPad settings application, there is a table view on the left, and when it's pressed the right side changes.
The radio buttons are there only to illustrate that I want more than one Document. I'm guessing I need more than one to handle this? Or perhaps I should place them all in a single NSDocument? Somehow that doesn't seem right.
To achieve what you want you need one window (NSWindow), one window controller and various views each with their own view controller. There are several ways you could set this up, all depending on your requirements:
You'd have at least 3 views (instances of NSView): one for the selection of the document class, one for the view selection and one for the content. Each view is controlled by a view controller (instance of NSViewController). Additionally you can opt to wrap the views in split views (NSSplitView) so your user can resize the real estate available to each view.
You have one window with a window controller. If you choose a Document based app template in Xcode, Xcode will generate a subclass of NSDocument which you can use as your window controller (or choose to use Core Data and Xcode will generate a subclass of NSPersistentDocument with all bells and whistles you need to access Core Data for document persistency).
So to come back to your questions:
1: Yes, but depending on your requirements. If Doc #1 is a completely different thing than Doc #2 than you might need to re-evaluate. For example Doc #1 might have completely different persistent requirements than #2.
2: There's no single scenario here, but one that worked for me: Take the project template for a document based app (with or without Core Data). Use the generated subclass of NSDocument (or NSPersistentDocument) as your window controller. Use NSView to implement the views in your window where each view is managed by its own controller, which is an instance of NSViewController.
I know this is an old question, but a way to do it how you want would be to use: ContainerViews and set their embed segue to be the view controllers you want.
The program I'm working on right now is a bit cumbersome, as it starts with a central menu, and then once the user chooses an option from it it opens their selection in a new window, when I've got a perfectly good window I can (at least apparently) repurpose to that effect. I've been reading the manual regarding views, and I understand what it's talking about regarding view hierarchy and such, but the method of swapping which view is active is confusing me. What do I need to do to have it "sweep away" the initial menu and replace it with another view containing the content the user selected?
Found a simple solution by using NSTabView to hold each of the views I'm looking for.
It sounds like you don't want to change views at all, but change the model you've loaded into the views.
The simplest way is probably to give the controller for the window a property by which the views can access another controller that owns a portion of the model (one such controller for every item in the menu). Then, you simply switch that controller.
In the setter for that property, you may need to send messages such as reloadData to some of the views, depending on what sort of views they are. Views that observe for changes using Bindings or KVO won't need this.
I have a composite widget that contains a disabled TextArea on an AbsotutePanel. Now I want to be able to drag the composite widget, starting from anywhere on it, including the disabled text area.
Is that possible?
If you want to drag a composite widget, you need to have a reference to the "drag handle" wich is one of the elements in the composite widget that implements HasAllMouseHandlers. The easiest (and in my mind, cleanest) way to do this is to have the composite widget extend the interface HasDragHandle wich requires the composite to have the method:
Widget getDragHandle(); the interface does not explicitly tell you so but the returned widget must be a widget implementing the HasAllMouseHandlers interface (or you'll get a runtime error).
(Non-composite widgets implementing HasAllMouseHandlers can be used directly)
I'd reccomend using a Label as a drag handle (it doesn't need to contain any text it could just be styled so the user understands it can be used for dragging), and not a form element because then you're overloading it's behaviour in a way the user most likely won't expect. I'm not really sure how a disabled element would work as a drag handle, quite possibly disabling an element will stop any mouse listners from working to so it won't work as a drag handle (haven't tried it though).
Or, try putting your widget into a FocusPanel, which is already enabled for drag 'n drop anyway. I've done this with a TextBox and a button, and it seems to work fine. Disabling the widget inside of the FocusPanel also keeps it from accidentally being activated.