Leopard problem: rotating buttons

  • I've written a program, SeisMaCalibrate, which calibrates the Sudden
    Motion Sensor on the user's laptop for later use by my seismic
    graphing program SeisMac. To calibrate, you have to perform three
    steps with the laptop in three different physical orientations: one
    sitting on its body, one sitting on its left edge, and one on its
    back with the body pointing straight up.

    The part I love about this (probably unique) user interface is that
    for the second step, the contents of the window, with
    constantly-updating text and buttons, are all rotated 90 degrees
    clockwise so that they're only upright if you sit the laptop on its
    left edge:

    <http://www.suitable.com/temp/SeisMaCalibrateTiger.png>

    Problem on Leopard: although everything works, the NSButton
    backgrounds don't rotate:

    <http://www.suitable.com/temp/SeisMaCalibrateLeopard.png>

    Oddly, the clickable areas of the NSButtons are properly rotated.
    (I'm guessing this is an obscure bug in NSButton drawing under
    Leopard.)

    Here's the code I use to do the rotation. I use a tab view (with no
    tabs) to manage the eight screens of the calibration process, and
    rotate the relevant view thusly:

    NSView *viewItem = [[tabView tabViewItemAtIndex:STEP_TWO] view];
    NSRect rect = [viewItem bounds];
    rect.origin.x = rect.size.width;
    [viewItem rotateByAngle:-90];
    [viewItem setBounds:rect];

    I've come up with a couple of not-so-great workarounds:

    - Take screen shots of the various button states in Tiger and then
    switch to using my own images to generate the buttons. ('Twould be
    ugly to code and get right, and the resulting button wouldn't do that
    lovely throbbing thing...)

    - Build my own button class which sets up an invisible NSView
    containing an NSButton. My class would route mouse events to the
    private view, and then repeatedly copy the appearance of the private
    view to the button's rectangle. (Again, ugly to get right, and a
    performance hog.)

    Any ideas? Should I use up one of my Technical Support Incidents on this?

    Thanks,
    Dan
    --
    Daniel T. Griscom            <griscom...>
    Suitable Systems              http://www.suitable.com/
    1 Centre Street, Suite 204    (781) 665-0053
    Wakefield, MA  01880-2400
  • At 8:45 AM -0600 11/3/07, Bill Dudney wrote:
    > Hi Daniel,
    >
    > Try making the buttons layer backed and then set their rotation angle.

    I tried calling [viewItem setWantsLayer:YES] without any rotation,
    but the buttons then wouldn't function, and the first time I showed
    the views the contents were somewhat blurry and distorted (subsequent
    displays were fine).

    > I've not tried it but I have seen a demo app that did a bunch of
    > rotation and other even stranger things with controls that were
    > layer backed.

    Any idea what the name of this demo was, or where I could find it?

    Thanks,
    Dan

    --
    Daniel T. Griscom            <griscom...>
    Suitable Systems              http://www.suitable.com/
    1 Centre Street, Suite 204    (781) 665-0053
    Wakefield, MA  01880-2400
  • Hi Daniel,

    I looked and could not find it, I think the example was from WWDC
    2006. If you are paid ADC you can get to the session on itunes.

    I went ahead and built a really simple app that has 2 buttons, one is
    layer backed (labeled beeper) the other is not (labeled rotate).  When
    you hit rotate the beeper button rotates an additional 15 degrees from
    where it is, when you hit beeper it beeps.

    The UI is ugly but its not mean to be an example of nice UI :)

    http://bill.dudney.net/roller/objc/resource/LayerBackedControls.zip

    Is the url to grab the project.

    There is a bug in IB with layer backed views, you should make the
    connections to and from the button before you turn on layer backing
    otherwise the button becomes fairly persistent about not being
    selected or connected to.

    I'm not sure about why the button would not function after calling
    setWantsLayer: I've not experienced that but most of the time when I
    call that method I'm setting the view to use a layer I created. If I'm
    not going to set the view to use my layer I typically just use the
    switch in IB. Which theoretically should not be different than calling
    the method but in practice probably is a little different.

    HTH,

    -bd-
    http://bill.dudney.net/roller/objc

    > At 8:45 AM -0600 11/3/07, Bill Dudney wrote:
    >> Hi Daniel,
    >>
    >> Try making the buttons layer backed and then set their rotation
    >> angle.
    >
    > I tried calling [viewItem setWantsLayer:YES] without any rotation,
    > but the buttons then wouldn't function, and the first time I showed
    > the views the contents were somewhat blurry and distorted
    > (subsequent displays were fine).
    >
    >> I've not tried it but I have seen a demo app that did a bunch of
    >> rotation and other even stranger things with controls that were
    >> layer backed.
    >
    > Any idea what the name of this demo was, or where I could find it?
    >
    >
    > Thanks,
    > Dan
    >
    > --
    > Daniel T. Griscom            <griscom...>
    > Suitable Systems              http://www.suitable.com/
    > 1 Centre Street, Suite 204    (781) 665-0053
    > Wakefield, MA  01880-2400
  • On Nov 4, 2007, at 7:55 AM, Bill Dudney wrote:

    > I went ahead and built a really simple app that has 2 buttons, one
    > is layer backed (labeled beeper) the other is not (labeled rotate).
    > When you hit rotate the beeper button rotates an additional 15
    > degrees from where it is, when you hit beeper it beeps.
    >
    > The UI is ugly but its not mean to be an example of nice UI :)
    >
    > http://bill.dudney.net/roller/objc/resource/LayerBackedControls.zip
    >
    > Is the url to grab the project.

    I don't know if anyone else is seeing this, but there's a bug in how
    the rotated button is drawn whenever its angle is some multiple of 90
    degrees:

    90: text normal, button is a very small circle, like a radio button,
    but clickable region is as wide as button should be
    180: Button is normal width, but has no rounded ends - just two
    straight line top and bottom borders. Clickable region is as it should
    be.
    270: text normal, button is a combination of the two above -
    orientation is off by 90 degrees (i.e., it's horizontal when it should
    be vertical, and its extent is only as wide as the button is tall. No
    rounded corners, just top and bottom borders.
    360: normal

    all other angles are correct, and this pattern repeats as you cycle.

    regards

    Ralph

    Raffael Cavallaro, Ph.D.
    <raffaelcavallaro...>
  • At 9:51 AM -0500 11/4/07, Raffael Cavallaro wrote:
    > On Nov 4, 2007, at 7:55 AM, Bill Dudney wrote:
    >
    >> I went ahead and built a really simple app that has 2 buttons, one
    >> is layer backed (labeled beeper) the other is not (labeled
    >> rotate).
    >> When you hit rotate the beeper button rotates an additional 15
    >> degrees from where it is, when you hit beeper it beeps.
    >>
    >> The UI is ugly but its not mean to be an example of nice UI :)
    >>
    >> http://bill.dudney.net/roller/objc/resource/LayerBackedControls.zip
    >>
    >> Is the url to grab the project.

    It was very kind of you, Bill, to whip up that demo, but...

    > I don't know if anyone else is seeing this, but there's a bug in how
    > the rotated button is drawn whenever its angle is some multiple of
    > 90 degrees:

    Bingo!!

    > 270: text normal, button is a combination of the two above -
    > orientation is off by 90 degrees (i.e., it's horizontal when it
    > should be vertical, and its extent is only as wide as the button is
    > tall. No rounded corners, just top and bottom borders.

    I'm rotating by -90 degrees, but not surprisingly see the same thing.

    > all other angles are correct, and this pattern repeats as you cycle.

    This observation led to a successful workaround: instead of setting
    the rotation to -90, set it to -89.999995 (the closest value to -90
    that still dodges the bug). The results:

    - Everything looks fine under Tiger

    - Everything looks fine under Leopard, EXCEPT that the text within
    the default button is blurry when not clicked. Very strange, but
    tolerable when compared to the alternatives.

    Raffael: have you reported this bug? If not, I will.

    I'm going to burn a tech support incident to see if there's a better
    workaround. I'll let you all know what I find out.

    Thanks for the help,
    Dan

    --
    Daniel T. Griscom            <griscom...>
    Suitable Systems              http://www.suitable.com/
    1 Centre Street, Suite 204    (781) 665-0053
    Wakefield, MA  01880-2400
  • On Nov 4, 2007, at 10:49 AM, Daniel Griscom wrote:

    > Raffael: have you reported this bug? If not, I will.

    Go ahead - you seem much more familiar with the problem than I am.

    good luck,

    regards,

    Ralph

    Raffael Cavallaro, Ph.D.
    <raffaelcavallaro...>
  • Here is a semi-workaround for now.... it uses core animation.
    It involves wrapping and NSView inside of an NSBox, and rotating the
    view using core animation's (the View's) backing CALayer.

    http://homepage.mac.com/son_gohan/Cocoa/LayerBackedControlsSortaFixed.zip

    The only problem is that the tracking rect for the button doesn't get
    rotated, so clicking only works in the middle of the button.
    Have you taken a look at the CocoaSlides example?

    Andre

    On $BJ?@.(B 19/11/05, at 2:01, Raffael Cavallaro wrote:

    >
    > On Nov 4, 2007, at 10:49 AM, Daniel Griscom wrote:
    >
    >> Raffael: have you reported this bug? If not, I will.
    >
    > Go ahead - you seem much more familiar with the problem than I am.
    >
    > good luck,
    >
    > regards,
    >
    > Ralph
    >
    >
    > Raffael Cavallaro, Ph.D.
    > <raffaelcavallaro...>
  • Hi All,

    Sorry, I forgot to turn on layer backing in the content view of the
    window. If you do that the button displays properly at all angles.
    There are a couple of places where the text is not as crisp as it
    could be but over all it looks pretty good, esp at the 90degree
    increments.

    Also sorry it took so long to get back to you.

    Anyway, I posted an updated version (under the same zip file and url).

    http://bill.dudney.net/roller/objc/resource/LayerBackedControls.zip

    TTFN,

    -bd-
    http://bill.dudney.net/roller/objc

    On Nov 4, 2007, at 6:20 PM, <listposter...> wrote:

    > Here is a semi-workaround for now.... it uses core animation.
    > It involves wrapping and NSView inside of an NSBox, and rotating the
    > view using core animation's (the View's) backing CALayer.
    >
    > http://homepage.mac.com/son_gohan/Cocoa/LayerBackedControlsSortaFixed.zip
    >
    > The only problem is that the tracking rect for the button doesn't
    > get rotated, so clicking only works in the middle of the button.
    > Have you taken a look at the CocoaSlides example?
    >
    > Andre
    >
    > On $BJ?@.(B 19/11/05, at 2:01, Raffael Cavallaro wrote:
    >
    >>
    >> On Nov 4, 2007, at 10:49 AM, Daniel Griscom wrote:
    >>
    >>> Raffael: have you reported this bug? If not, I will.
    >>
    >> Go ahead - you seem much more familiar with the problem than I am.
    >>
    >> good luck,
    >>
    >> regards,
    >>
    >> Ralph
    >>
    >>
    >> Raffael Cavallaro, Ph.D.
    >> <raffaelcavallaro...>

previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today