Skip to content
This repository has been archived by the owner on Nov 1, 2017. It is now read-only.

TUISlider #151

Closed
wants to merge 8 commits into from
Closed

TUISlider #151

wants to merge 8 commits into from

Conversation

avaidyam
Copy link

Basically a simple slider for TwUI. Drawing is abstracted into overridable methods, and it uses NSSliderCell to draw itself, while still remaining customizable. This allows the slider to be drawn by CoreUI, and remain OS dependent in look and feel.

@jwilling
Copy link

Hmm, the tracking isn't correct on this. When the slider is near the edges it tracks from the respective edge instead of the center of the knob.

@avaidyam
Copy link
Author

@jwilling Just noticed that, and I'll fix that soon. I forgot to even send actions when the value changed... oops!

@ghost ghost assigned CodaFi Dec 27, 2012

// The number of the slider's tick marks. The tick marks assigned to
// the minimum and maximum values are included.
@property (nonatomic, assign) NSInteger numberOfTickMarks;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why this isn't unsigned?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CodaFi Because turtles wrote AppKit and I copied AppKit headers. I should have copied UIKit headers, knowing that lemurs wrote UIKit. /cries in corner.

English: Yeah, go blame AppKit headers as I fix this issue.

@CodaFi
Copy link

CodaFi commented Dec 28, 2012

There appears to be a noticeable delay between when the slider is moved, and when the cursor changes to the east-west image. Any idea why?

@@ -42,6 +42,9 @@ - (id)initWithStyle:(TUITableViewCellStyle)style reuseIdentifier:(NSString *)reu
_textRenderer.shadowColor = [NSColor whiteColor];
_textRenderer.shadowOffset = CGSizeMake(0, 1);

TUISlider *slider = [[TUISlider alloc] initWithFrame:CGRectMake(5, 5, 250, 32 - 5)];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This frame overlaps the text in the cell pretty bad, especially when tick marks are on. Also, 32-5?

@avaidyam
Copy link
Author

@CodaFi "east-west image"? I don't see much lag on my MBP... could you explain what you're seeing in more detail? :) Please and thank you!

@avaidyam
Copy link
Author

@CodaFi I've made the changes you've indicated. (On that note, merry late christmas?)


+ (TUIExtendedSliderCell *)sharedGraphicsRenderer {
static TUIExtendedSliderCell *_backingCell;
if(_backingCell == nil)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is subject to race conditions. Please use dispatch_once instead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jwilling Fixed!

@avaidyam
Copy link
Author

@jwilling @CodaFi Any idea on how to animate this kind of a view? I know custom animations are possible with a CALayer animation, but how would I do it with a TUIView/UIView? Would a CVDisplayLink work?

@jwilling
Copy link

What do you mean by animate? What is there to animate, exactly?


// Set up the graphics renderer before drawing. Although it
// seems like a burden, it takes around 25ms to configure.
[slider setControlSize:(NSControlSize)self.controlSize];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it might take 25ms to set the properties, we can't be sure that this will not cause an invalidation of some key aspect of the cell, thereby slowing down the drawing.

This probably means that each of the properties will need to have their setters overridden to forward it onto the cell itself.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jwilling The reason I set it in the drawing method was so that the "private graphics renderer" would be isolated from any subclasses interested in drawing. What we could do is check if the properties were "dirtied" and if they were, then set everything again.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "isolated"? How does setting it here vs. modifying the setters affect anything?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If subclasses are going to modify the drawing (very much presumably by not using an NSSliderCell to do it), then setting these properties is a waste. My point here is not to re-create an NSSlider wrapper over NSSliderCell, but to simply use it for graphics rendering, hence sharedGraphicsRenderer being a class method. There's only one of these for all TUIKit framework existence because I don't want another NSControl/NSCell mess. If I did, I'd be using AppKit.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay then, please check if these properties are different than what the current values is before setting them.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that again might take longer... the real implication here is that this sharedGraphicsRenderer is "class-pervasive", which means there's only one for all sliders on screen. That's why we need to set these properties each time. Each slider might be differently rendered, but only one cell is taking care of them (I guess AppKit developers who decided on the NSCell segregation are quite happy....?)

@avaidyam
Copy link
Author

@jwilling I wanted to animate the slider min/max/value properties, like UISlider does. This is possible with CVDisplayLink but that just disregards any sort of TUIView animation properties (curve, duration, etc).

@jwilling
Copy link

CVDisplayLink is drastic and shouldn't be used lightly. These UISlider animations occur when wrapped in a UIView animation block, you say?

@avaidyam
Copy link
Author

Agreed, which is why I'm puzzled as to implementing custom TUIView animations. I'm not sure if UISlider animations are implicit UIView animations, given there being ...animated: setter methods. I would very much like if it were possible in TUIView to allow implicit animations when inside animation contexts, however. 😄

[slider setDoubleValue:self.value];
[slider setKnobThickness:self.knobThickness];
[slider setNumberOfTickMarks:self.numberOfTickMarks];
[slider setTickMarkPosition:(NSTickMarkPosition)self.drawTickMarksOnAlternateSide];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cast should not be here and could be potentially unsafe. Evaluate the current setting and pass in the appropriate type.


// Defer the drawing, but allow the cell to cache the rects.
- (void)calcDrawInfo:(NSRect)rect {
[NSImage tui_imageWithSize:rect.size drawing:^(CGContextRef ctx) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this? You're not only ignoring the return value of that function (and thereby abusing it), but you're also drawing into nothing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am indeed abusing it and drawing into nothing: if you look above where the track is drawn, I need the slider's knobRect to highlight the slider at exactly the location of the knob. This knobRect is only passed (below in drawKnob:) after drawWithFrame:inView: is called, which is why I draw into nothing. The cell's drawing is deferred to allow the knobRect to "propagate". It's really not a performance hit, but I agree it is a massive abuse of API. However, as justification, that's the only way the knob can be drawn highlighted.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also like to add that this is only possible because NSCell instances are supposed to be highly efficient at drawing, otherwise, the point to cell-backed NSTableViews is lost. So, rest assured, this shouldn't cause a massive gaping hole in drawing speeds.

@avaidyam
Copy link
Author

@jwilling @CodaFi Any other issues?

@jwilling
Copy link

@galaxas0 Please don't be impatient; this hasn't been forgotten.

@avaidyam
Copy link
Author

@jwilling I'm sorry! 🐼 I'll just let it sit then. I'm just trying to get all my PRs through faster... :P

@jspahrsummers
Copy link

👎 The use of NSCell here is extremely hacky and liable to break in future OS updates. Having to jump through hoops like that at all defeats much of the purpose of TwUI, which is to avoid a lot of the crappy behaviors of AppKit.

It would make more much sense, IMO, to use a TUIViewNSViewContainer and put a real NSSlider in there. If you want customization, why not subclass the real class?

@avaidyam
Copy link
Author

@jspahrsummers The behavior of NSCell in regards to NSSliderCell has not changed for many years now: I'm not doing anything special except drawing it twice to calculate where the knob is (so highlighting works). The TUIViewNSViewContainer has many flaws (clipping and focus rings being two) that keep me away from using it.

@jspahrsummers
Copy link

The behavior of NSCell in regards to NSSliderCell has not changed for many years now

That doesn't say anything about whether it might break in the future.

I'm not doing anything special except drawing it twice to calculate where the knob is (so highlighting works).

This is what's hacky.

The TUIViewNSViewContainer has many flaws (clipping and focus rings being two) that keep me away from using it.

Adding more direct uses of AppKit to avoid bridging bugs doesn't help fix those bugs, and contradicts the purpose of the framework.

@avaidyam
Copy link
Author

Alright, understood. Does this go for the TUIButton PR as well?

@jspahrsummers
Copy link

Let's talk about that in #149 so that the comments are properly contextual.

@avaidyam
Copy link
Author

👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants