Cocoa - Rolling a panel out the side of a window? - objective-c

I'm hoping this is ver straightforward. But basically I'd love for my app to be able to "roll out" a Panel/View to the right of my app's window.
I've achieved something similar (rolling a panel down, over the existing window) by doing:
[NSApp beginSheet:myPanel
modalForWindow: [self.view window]
modalDelegate: self
didEndSelector: #selector(sheetDidEnd: returnCode: contextInfo:)
contextInfo: nil];
But how can I have a panel roll out the side of my window? I basically want to have like a sidebar, that if a user clicks the button, it will roll out + display more information. Does that make sense?
Thanks!

Couple of things (Edit: okay, three):
First, others suggested NSDrawer, but users were at best lukewarm on the idea of drawers years ago. These days drawers are nearly universally despised. Consider using NSSplitView (with the thin 1-pixel border) and use its -animator to animate the opening/closing.
Second, if you specifically want the "sheet" effect (a sheet appearing to come out of a slit in the window or even a view), you're in for a whole world of customization "fun" to reproduce this effect, since there's positively no public API to tell it to come out of a window/view vertically (vs. horizontally).
Third, I'd argue customizing a standard UI behavior in this way (the sheet example in my second point) is almost never the way to go. There are plenty of reasons to provide custom UI when the existing doesn't do what you need it to do, but making such an obvious change to standard behavior for the hell of it tends to be frowned upon by Mac users. It's one of the main complaints they have against third-party Windows apps (no consistency in their UI). So don't do the vertical sheet thing for your users' sake. :-)

If you want your panel to roll out away from the window - you should use NSDrawer. Otherwise - you'll have to code something custom and I don't think that it's going to be a good UX.

Related

Cocoa: Update views outside NSWindow's content view during live window resizing?

I have a standard NSWindow with a toolbar. One of the toolbar's items is a custom view -- specifically, an NSTextField. (More specifically, it's a timer app -- the timer's controls as well as the digital display are all within the toolbar, with other stuff in the window's content area. The NSTextField is the digital display.)
Ordinarily, I just update the timer every second by changing the 'stringValue' property of the NSTextField, which causes it to update itself. But during a live window resize, even though the code that updates the 'stringValue' property is running (which I have verified with NSLog), the NSTextField doesn't draw itself again until the window resizing is done. Meanwhile, the stuff inside the content area is updating itself just fine.
I've tried all the ways I know to tell the NSTextField to draw itself, but it just refuses to happen until the live resize is done. Any ideas? Obviously it must be possible somehow, as the toolbar gets resized along with the rest of the window -- so you'd think it would be possible to force it to redraw one or more of its subviews as it is moving them around. I'm assuming I can hack this together by subclassing something, but my Cocoa-fu is not yet strong enough to figure out the easiest/most proper way to do so.
Thanks in advance...
EDIT: I kind of figured out a solution -- it's not great but it mostly works for now. It's in my comments below.
Just invoke -[NSWindow displayIfNeeded] after marking the view as needing display. I encountered this problem when implementing the Mac driver for Wine (an open-source project for running Windows software on OS X and other Unix-like OSes).
http://source.winehq.org/source/dlls/winemac.drv/cocoa_window.m?v=wine-1.7.11#L1905
(That's LGPL code, so you want to consider before copying it. But you can learn implementation techniques from it without worry.)

Make a custom UIView perform the Speak action

In most Apple-provided controls, you can tap and hold on the text, and get the copy/paste menu, which usually has "Speak" at the end.
I have a custom control (UIView descendant) I want to do the same with.
I can pop up my own menu no problem, and while I dont need them, copy and paste are built in, but is there any (appstore legal) way to make the control "speak" on the users command, given a block of text?
I don't want to trigger it in code without user interaction. Well, I do, but I suspect thats going to be impossible, or there would be lots of code/docs around to do it :)
VoiceOver is not an option, as the app is targeted at kids, and the change in gestures with voiceover is likely to cause problems. I already have the accessability properties set with the appropriate data, so if it is on, then that works.
Thanks!

iOS text popup with clickable links

I'm looking for a simple solution to presenting popup text in an iOS app that contains text with hyperlinks.
At the moment, my text pops up as a UIAlertView. The user has a 'Close' button below which dismisses the box. However, this class (UIAlertView) doesn't allow the use of hyperlinks within the message text. I understand that creating a whole new custom UIAlertView is frowned upon (not to mention probably overkill for what I want to achieve).
Perhaps I'm barking up the wrong tree by using UIAlertViews. I'm new to iOS and don't know the scope of what's available. Essentially, I need a dialog (or window) to pop up, containing a string of text, a (close/back/dismiss) button, and possible hyperlinks within the text. Those hyperlinks in turn launch other popups/windows/dialogs of their own.
What I'm working on here is a simple dictionary application. It's a table view containing terms. The terms lead to definitions, and in most cases, the definitions themselves reference other terms. Fairly simple, and if possible I'd like to use standard API classes.
Any wisdom would be appreciated. If I truly have to go down the route of creating my own custom UIAlertView class, then sobeit! In this case, some pointers for lightweight class creation would be appreciated. I'm not looking to add fancy colours or anything, just the ability to click on bits of text.
I think you'll need to create your own UIView sub-class to do the trick, controlled by a UIViewController subclass. One trick I've used to make it look more like an alert view is to have your main popup view embedded in a fullscreen view with a clear background.
In general, Apple SDKs make it really easy to do standard things (UIAlertView), but if you want to tinker with it (embedded links), you need to do it yourself.

Clicking through NSWindow/CALayer

So I'm working on an issue I have when trying to do some simple animation using CAKeyframeAnimation, and I believe my problem is more related to not fully understanding how NSWindow, NSView, and CALayer work together. 
I have two main objects in question. MyContainerWindow (NSWindow subclass) and MyMovableView (NSView subclass). My goal is to be able to animate MyMovableView back and forth across the screen, while maintaining the ability to click on anything through MyContainerWindow unless you are clicking on wherever MyMovableView is. I am able to accomplish the first part fine, by calling -addAnimation:forKeyPath: on myMovableView.layer, and everything is great except I can't click through MyContainerWindow. I could make the window smaller, but then the animation would clip by the bounds of the window.
Important points: 
1) MyContainerWindow is initWithFrame to [[NSScreen mainScreen] frame], NSBorderlessWindowMask, defer no, buffered
2) I setWantsLayer:TRUE to MyMovableView
3) MyContainerWindow is clear, and I want it to be as if there wasnt a window at all, but need it so I have a larger canvas to animate on.
Is there something obvious I'm missing to be able to click through an NSWindow?
Thanks in advance!
My solution in this scenario was actually to use:
[self ignoresMouseEvents:YES];
I originally was hoping to be able to retain the mouse events on the specific CALayer that I'm animating, but upon some further research I understand this comes with the cost of custom drawing everything from scratch, which is not ideal for this particular project.

Any "fundamentals-oriented" example of NSScroller out there?

I'm looking for some kind of a basic, straightforward example of how to work with a pair of NSScrollers in an NSScrollView with a custom NSView.
There are sporadic examples out there, largely consisting of contrived examples using programatically created interfaces, or based on the assumption that the developer is working with a typical ImageView or TextView. Even the Sketch example is based on an NSView that uses the Page Setup in the Print dialog for the bounds, and everything is managed by Cocoa. So there's no real discussion or examples anywhere of how make it all work using a custom Model (though that may be part of the problem, because what does one base the Model on?). Even Apple's own documentation is dodgy here.
Essentially, I have a sub-classed NSView enbedded in an NSScrollView (per the Scoll View Guide), that a user can click in the view to create, edit and delete objects, much like an illustration program. The Model is those objects that are just data wrappers that simply record their position for drawRect: to use. The height and width are based on custom values that are being translated into pixels as needed.
My problem is that all of the examples I have found are based on either a text editor, an image viewer, or uses the standard document sizes in the Page Setup dialog. Because these are common document types, Cocoa basically manages for the developer, so the interaction code is more or less hidden (or I'm just not seeing it for what it is). My project doesn't fit any of those needs, and I have no need for printing. Thrusting my Model into the documentView property wouldn't work.
I'm just looking for a simple example on how to initialize the NSScrollers with a custom, object-oriented Model (the documentView), and handle scrolling and updating based on user action, such as when the user drags a smattering of objects off to the left or down or the window gets resized. I think I'm close to getting it all together, but I'm missing the jumping off point that ties the controls to document.
(Not that it matters in a Cocoa question, but when I did this in REALbasic, I would simply calculate and apply the MaxX, MaxY to a ScrollBar's Maximum value based on user actions, watch the position in the ScrollBar when the user clicks, and draw as needed. NSScrollers in the NSScrollView context aren't nearly as obvious to me, it seems.)
I appreciate the time taken by everyone, but I'm updating with more information in the hopes of getting an answer I can use. I'm sorry, but none of this is making sense, Apple's documents are obtuse, but perhaps I'm missing something painfully obvious here...
I have an array of objects sitting in a subclassed NSDocument which are data holders that tell drawRect what and where to draw. This is straight from the Sketch example. The Sketch example uses the document sizes in the Page Setup dialog for the size, so there's nothing to show here. I'm cool with Cocoa handling the state of the scroll bars, but how do I link up the ScrollView to see the initial editor's state held in the NSDocument and updates to those objects and the editor? Do I calculate my own NSRect and pass that to the NSScrollView? Where and how? Am I doing this in my custom NSView which has been embedded in the NSScrollView or my NSDocument in init? The NSScrollView isn't created programmatically (there's no easy way of doing that), so it's all sitting in Interface Builder waiting to be hooked up. I'm missing the hook up bit.
Perhaps I'm wearing my "I don't get it" cap this week, but this can't be this difficult. Illustration apps, MIDI Editors, and countless other similar custom apps do this all the time.
SOLVED (mostly):
I think I have this sorted out now, though it's probably not the best implementation.
My document class now has a NSRect DocumentRect property that looks at all of its objects and gives back a new NSRect based on their location. I call it in my subclassed NSView's mouse events with
[self setFrame:[[self EditorDocument] DocumentRect]];
This updates the size of the View based on user interaction, and the window now handles the scrolling where it didn't before. At this point I'm figuring out how to get the frame to expand while dragging, but at least I now have the fundamental concept I was missing.
The answer given pointed me in the direction I needed to go here (documentView requiring a view, which translated to looking at the NSView class), so Peter gets the credit. Thanks so much for help.
The document view isn't a model, it's a view. That's why it's called the document view.
The reason there are so few examples on working with NSScrollers directly is because you normally don't. You work with NSScrollView and let it handle the scrollers for you.
All you need to do is make a view big enough to show the entire model, then set that as the document view of the scroll view. From there, it should Just Work. You don't need to manage any of the scrolling-related numbers yourself; Cocoa handles them for you.
For details, see the Scroll View Programming Guide.