mirror of
https://github.com/ONLYOFFICE/desktop-sdk.git
synced 2026-03-31 10:23:12 +08:00
Add custom sliders
This commit is contained in:
@ -49,8 +49,9 @@ void CCefViewMedia::showMediaControl(NSEditorApi::CAscExternalMediaPlayerCommand
|
||||
}
|
||||
|
||||
m_player_view->SetMedia(data->get_Url());
|
||||
// TODO: remove play
|
||||
// TODO: remove play and mute
|
||||
m_player_view->Play();
|
||||
m_player_view->ChangeVolume(0);
|
||||
|
||||
int nVolume = data->get_Volume();
|
||||
if (data->get_Mute() || m_pCefView->IsPresentationReporter()) {
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#import "iconpushbutton.h"
|
||||
#import "timelabel.h"
|
||||
#import "slider.h"
|
||||
#import "utils.h"
|
||||
|
||||
// Helper functions for maintaining auto layout
|
||||
@ -45,6 +46,8 @@ void setRightConstraintsToView(NSView* view, NSLayoutYAxisAnchor* top_anchor, NS
|
||||
NSIconPushButton* m_btn_rewind_back;
|
||||
// text labels
|
||||
NSTimeLabel* m_time_label;
|
||||
// sliders
|
||||
NSStyledSlider* m_slider_video;
|
||||
// constraints
|
||||
NSLayoutConstraint* m_time_label_width_constraint;
|
||||
NSLayoutConstraint* m_time_label_height_constraint;
|
||||
@ -72,7 +75,7 @@ void setRightConstraintsToView(NSView* view, NSLayoutYAxisAnchor* top_anchor, NS
|
||||
const NSSize button_size = NSMakeSize(button_width, button_width);
|
||||
|
||||
// play button
|
||||
m_btn_play = [[NSIconPushButton alloc] initWithIconName:@"btn-play" size:button_size skin:&m_skin];
|
||||
m_btn_play = [[NSIconPushButton alloc] initWithIconName:@"btn-play" size:button_size style:&m_skin.button];
|
||||
[self addSubview:m_btn_play];
|
||||
setLeftConstraintsToView(m_btn_play, self.topAnchor, self.leftAnchor, button_y_offset, button_space_between, button_size);
|
||||
#if !__has_feature(objc_arc)
|
||||
@ -80,7 +83,7 @@ void setRightConstraintsToView(NSView* view, NSLayoutYAxisAnchor* top_anchor, NS
|
||||
#endif
|
||||
|
||||
// volume button
|
||||
m_btn_volume = [[NSIconPushButton alloc] initWithIconName:@"btn-volume-2" size:button_size skin:&m_skin];
|
||||
m_btn_volume = [[NSIconPushButton alloc] initWithIconName:@"btn-volume-2" size:button_size style:&m_skin.button];
|
||||
[self addSubview:m_btn_volume];
|
||||
setRightConstraintsToView(m_btn_volume, self.topAnchor, self.rightAnchor, button_y_offset, button_space_between, button_size);
|
||||
#if !__has_feature(objc_arc)
|
||||
@ -88,14 +91,14 @@ void setRightConstraintsToView(NSView* view, NSLayoutYAxisAnchor* top_anchor, NS
|
||||
#endif
|
||||
|
||||
// time label
|
||||
m_time_label = [[NSTimeLabel alloc] initWithSkin:&m_skin];
|
||||
m_time_label = [[NSTimeLabel alloc] initWithStyle:&m_skin.time_label];
|
||||
[self addSubview:m_time_label];
|
||||
NSSize text_bounds = [m_time_label getBoundingBoxSize];
|
||||
// manually set all constraints
|
||||
// manually set all text label constraints
|
||||
m_time_label.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[m_time_label.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:0].active = YES;
|
||||
[m_time_label.rightAnchor constraintEqualToAnchor:m_btn_volume.leftAnchor constant:-button_space_between].active = YES;
|
||||
// we need to save width and height constraints becuase changing skin may affect text width and height
|
||||
// we need to save width and height constraints because changing skin may affect text width and height
|
||||
m_time_label_width_constraint = [m_time_label.widthAnchor constraintEqualToConstant:text_bounds.width];
|
||||
m_time_label_width_constraint.active = YES;
|
||||
m_time_label_height_constraint = [m_time_label.heightAnchor constraintEqualToConstant:text_bounds.height];
|
||||
@ -105,7 +108,7 @@ void setRightConstraintsToView(NSView* view, NSLayoutYAxisAnchor* top_anchor, NS
|
||||
#endif
|
||||
|
||||
// rewind forward button
|
||||
m_btn_rewind_forward = [[NSIconPushButton alloc] initWithIconName:@"btn-rewind-forward" size:button_size skin:&m_skin];
|
||||
m_btn_rewind_forward = [[NSIconPushButton alloc] initWithIconName:@"btn-rewind-forward" size:button_size style:&m_skin.button];
|
||||
[self addSubview:m_btn_rewind_forward];
|
||||
setRightConstraintsToView(m_btn_rewind_forward, self.topAnchor, m_time_label.leftAnchor, button_y_offset, button_space_between, button_size);
|
||||
#if !__has_feature(objc_arc)
|
||||
@ -113,7 +116,7 @@ void setRightConstraintsToView(NSView* view, NSLayoutYAxisAnchor* top_anchor, NS
|
||||
#endif
|
||||
|
||||
// rewind back button
|
||||
m_btn_rewind_back = [[NSIconPushButton alloc] initWithIconName:@"btn-rewind-back" size:button_size skin:&m_skin];
|
||||
m_btn_rewind_back = [[NSIconPushButton alloc] initWithIconName:@"btn-rewind-back" size:button_size style:&m_skin.button];
|
||||
[self addSubview:m_btn_rewind_back];
|
||||
setRightConstraintsToView(m_btn_rewind_back, self.topAnchor, m_btn_rewind_forward.leftAnchor, button_y_offset, button_space_between, button_size);
|
||||
#if !__has_feature(objc_arc)
|
||||
@ -121,7 +124,18 @@ void setRightConstraintsToView(NSView* view, NSLayoutYAxisAnchor* top_anchor, NS
|
||||
#endif
|
||||
|
||||
// video slider
|
||||
// TODO:
|
||||
m_slider_video = [[NSStyledSlider alloc] initWithStyle:&m_skin.video_slider];
|
||||
[self addSubview:m_slider_video];
|
||||
// manually set all constraints
|
||||
m_slider_video.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[m_slider_video.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:0].active = YES;
|
||||
[m_slider_video.leftAnchor constraintEqualToAnchor:m_btn_play.rightAnchor constant:button_space_between].active = YES;
|
||||
[m_slider_video.rightAnchor constraintEqualToAnchor:m_btn_rewind_back.leftAnchor constant:-button_space_between].active = YES;
|
||||
// TODO: the whole slider area on panel becomes clickable because of this
|
||||
[m_slider_video.heightAnchor constraintEqualToConstant:frame_rect.size.height].active = YES;
|
||||
#if !__has_feature(objc_arc)
|
||||
[m_slider_video release];
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -154,6 +168,8 @@ void setRightConstraintsToView(NSView* view, NSLayoutYAxisAnchor* top_anchor, NS
|
||||
NSSize text_bounds = [m_time_label getBoundingBoxSize];
|
||||
m_time_label_width_constraint.constant = text_bounds.width;
|
||||
m_time_label_height_constraint.constant = text_bounds.height;
|
||||
// update sliders
|
||||
[m_slider_video updateStyle];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -24,6 +24,27 @@ struct CTimeLabelStyle {
|
||||
Color color;
|
||||
};
|
||||
|
||||
struct CSliderStyle {
|
||||
struct CTrackStyle {
|
||||
Color color; // color of the track (right of knob)
|
||||
Color fill_color; // color of the filled portion of the track (left of knob)
|
||||
int thickness;
|
||||
int border_radius;
|
||||
};
|
||||
|
||||
struct CKnobStyle {
|
||||
Color color;
|
||||
Color border_color;
|
||||
int thickness;
|
||||
int border_width = 0;
|
||||
int border_radius = 0;
|
||||
};
|
||||
|
||||
CTrackStyle track;
|
||||
bool is_knob_visible;
|
||||
CKnobStyle knob;
|
||||
};
|
||||
|
||||
class CFooterSkin {
|
||||
public:
|
||||
enum class Type {
|
||||
@ -49,19 +70,21 @@ public:
|
||||
CFooterStyle footer;
|
||||
CButtonStyle button;
|
||||
CTimeLabelStyle time_label;
|
||||
CSliderStyle video_slider;
|
||||
CSliderStyle volume_slider;
|
||||
|
||||
public:
|
||||
// some global constants (skin-independent)
|
||||
// buttons
|
||||
static constexpr int button_width = 30;
|
||||
static constexpr int button_y_offset = 5;
|
||||
static constexpr int button_space_between = 8;
|
||||
|
||||
// volume controls
|
||||
static constexpr int volume_control_width = 30;
|
||||
static constexpr int volume_control_height = 140;
|
||||
|
||||
static constexpr int volume_slider_width = 20;
|
||||
static constexpr int volume_slider_height = 120;
|
||||
|
||||
// general footer panel params
|
||||
static constexpr int border_radius = 5;
|
||||
};
|
||||
|
||||
|
||||
@ -13,15 +13,22 @@ CFooterSkin CFooterSkin::getSkin(Type type) {
|
||||
skin.button.bg_color_pressed = 0xCBCBCB;
|
||||
skin.button.border_radius = 3;
|
||||
|
||||
// skin.m_oSliderStyleOpt1.m_sAddColor = "#848484";
|
||||
// skin.m_oSliderStyleOpt1.m_sSubColor = "#E2E2E2";
|
||||
// skin.m_oSliderStyleOpt1.m_sHandleColor = "#FFFFFF";
|
||||
// skin.m_oSliderStyleOpt1.m_sHandleBorderColor = "#444444";
|
||||
skin.video_slider.track.color = 0xE2E2E2;
|
||||
skin.video_slider.track.fill_color = 0x848484;
|
||||
skin.video_slider.track.thickness = 8;
|
||||
skin.video_slider.track.border_radius = 4;
|
||||
skin.video_slider.is_knob_visible = false;
|
||||
|
||||
// skin.m_oSliderStyleOpt2.m_sAddColor = "#C0C0C0";
|
||||
// skin.m_oSliderStyleOpt2.m_sSubColor = "#E2E2E2";
|
||||
// skin.m_oSliderStyleOpt2.m_sHandleColor = "#FFFFFF";
|
||||
// skin.m_oSliderStyleOpt2.m_sHandleBorderColor = "#444444";
|
||||
skin.volume_slider.track.color = 0xE2E2E2;
|
||||
skin.volume_slider.track.fill_color = 0xC0C0C0;
|
||||
skin.volume_slider.track.thickness = 8;
|
||||
skin.volume_slider.track.border_radius = 4;
|
||||
skin.volume_slider.is_knob_visible = true;
|
||||
skin.volume_slider.knob.color = 0xFFFFFF;
|
||||
skin.volume_slider.knob.border_color = 0x444444;
|
||||
skin.volume_slider.knob.thickness = 16;
|
||||
skin.volume_slider.knob.border_width = 2;
|
||||
skin.volume_slider.knob.border_radius = 8;
|
||||
|
||||
skin.time_label.font_name = @"";
|
||||
skin.time_label.font_size = 14;
|
||||
@ -37,15 +44,22 @@ CFooterSkin CFooterSkin::getSkin(Type type) {
|
||||
skin.button.bg_color_pressed = 0x46494B;
|
||||
skin.button.border_radius = 3;
|
||||
|
||||
// skin.m_oSliderStyleOpt1.m_sAddColor = "#9B9B9B";
|
||||
// skin.m_oSliderStyleOpt1.m_sSubColor = "#545454";
|
||||
// skin.m_oSliderStyleOpt1.m_sHandleColor = "#FFFFFF";
|
||||
// skin.m_oSliderStyleOpt1.m_sHandleBorderColor = "#222222";
|
||||
skin.video_slider.track.color = 0x545454;
|
||||
skin.video_slider.track.fill_color = 0x9B9B9B;
|
||||
skin.video_slider.track.thickness = 8;
|
||||
skin.video_slider.track.border_radius = 4;
|
||||
skin.video_slider.is_knob_visible = false;
|
||||
|
||||
// skin.m_oSliderStyleOpt2.m_sAddColor = "#808080";
|
||||
// skin.m_oSliderStyleOpt2.m_sSubColor = "#545454";
|
||||
// skin.m_oSliderStyleOpt2.m_sHandleColor = "#FFFFFF";
|
||||
// skin.m_oSliderStyleOpt2.m_sHandleBorderColor = "#222222";
|
||||
skin.volume_slider.track.color = 0x545454;
|
||||
skin.volume_slider.track.fill_color = 0x808080;
|
||||
skin.volume_slider.track.thickness = 8;
|
||||
skin.volume_slider.track.border_radius = 4;
|
||||
skin.volume_slider.is_knob_visible = true;
|
||||
skin.volume_slider.knob.color = 0xFFFFFF;
|
||||
skin.volume_slider.knob.border_color = 0x222222;
|
||||
skin.volume_slider.knob.thickness = 16;
|
||||
skin.volume_slider.knob.border_width = 2;
|
||||
skin.volume_slider.knob.border_radius = 8;
|
||||
|
||||
skin.time_label.font_name = @"";
|
||||
skin.time_label.font_size = 14;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#import "footerskin.h"
|
||||
|
||||
@interface NSIconPushButton : NSButton
|
||||
- (instancetype)initWithIconName:(NSString*)icon_name size:(NSSize)size skin:(CFooterSkin*)skin;
|
||||
- (instancetype)initWithIconName:(NSString*)icon_name size:(NSSize)size style:(CButtonStyle*)style;
|
||||
- (void)dealloc;
|
||||
|
||||
// button appearance
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
@interface NSIconPushButton ()
|
||||
{
|
||||
CFooterSkin* m_skin;
|
||||
CButtonStyle* m_style;
|
||||
bool m_hovered;
|
||||
NSString* m_icon_name;
|
||||
}
|
||||
@ -12,13 +12,13 @@
|
||||
|
||||
@implementation NSIconPushButton
|
||||
|
||||
- (instancetype)initWithIconName:(NSString*)icon_name size:(NSSize)size skin:(CFooterSkin*)skin {
|
||||
- (instancetype)initWithIconName:(NSString*)icon_name size:(NSSize)size style:(CButtonStyle*)style {
|
||||
NSRect init_frame_rect = NSMakeRect(0, 0, size.width, size.height);
|
||||
self = [super initWithFrame:init_frame_rect];
|
||||
if (self) {
|
||||
[self setWantsLayer:YES];
|
||||
// apply skin
|
||||
m_skin = skin;
|
||||
m_style = style;
|
||||
m_icon_name = icon_name;
|
||||
[self updateStyle];
|
||||
// add mouse tracking for background color or/and icon changing
|
||||
@ -35,16 +35,16 @@
|
||||
}
|
||||
|
||||
- (void)updateStyle {
|
||||
self.layer.cornerRadius = m_skin->button.border_radius;
|
||||
self.layer.cornerRadius = m_style->border_radius;
|
||||
self.bordered = NO;
|
||||
self.layer.backgroundColor = [NSColorFromHex(m_skin->button.bg_color_regular) CGColor];
|
||||
self.layer.backgroundColor = [NSColorFromHex(m_style->bg_color_regular) CGColor];
|
||||
[self setIcon:m_icon_name];
|
||||
}
|
||||
|
||||
- (void)setIcon:(NSString*)icon_name {
|
||||
m_icon_name = icon_name;
|
||||
// TODO: are -2x png icons always suitable on mac platforms ???
|
||||
NSString* icon_full_name = [NSString stringWithFormat:@"%@%@%@", icon_name, m_skin->button.icon_postfix, @"-2x"];
|
||||
NSString* icon_full_name = [NSString stringWithFormat:@"%@%@%@", icon_name, m_style->icon_postfix, @"-2x"];
|
||||
NSString* icon_path = [[NSBundle mainBundle] pathForResource:icon_full_name ofType:@"png"];
|
||||
if (icon_path == nil) {
|
||||
NSLog(@"Error: could not load icon %@.png", icon_full_name);
|
||||
@ -60,25 +60,25 @@
|
||||
|
||||
- (void)mouseEntered:(NSEvent*)event {
|
||||
m_hovered = true;
|
||||
self.layer.backgroundColor = [NSColorFromHex(m_skin->button.bg_color_hovered) CGColor];
|
||||
self.layer.backgroundColor = [NSColorFromHex(m_style->bg_color_hovered) CGColor];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent*)event {
|
||||
m_hovered = false;
|
||||
self.layer.backgroundColor = [NSColorFromHex(m_skin->button.bg_color_regular) CGColor];
|
||||
self.layer.backgroundColor = [NSColorFromHex(m_style->bg_color_regular) CGColor];
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent*)event {
|
||||
self.layer.backgroundColor = [NSColorFromHex(m_skin->button.bg_color_pressed) CGColor];
|
||||
self.layer.backgroundColor = [NSColorFromHex(m_style->bg_color_pressed) CGColor];
|
||||
NSLog(@"debug: button pressed");
|
||||
}
|
||||
|
||||
- (void)mouseUp:(NSEvent*)event {
|
||||
CGColor* bg_color = nil;
|
||||
if (m_hovered) {
|
||||
bg_color = [NSColorFromHex(m_skin->button.bg_color_hovered) CGColor];
|
||||
bg_color = [NSColorFromHex(m_style->bg_color_hovered) CGColor];
|
||||
} else {
|
||||
bg_color = [NSColorFromHex(m_skin->button.bg_color_regular) CGColor];
|
||||
bg_color = [NSColorFromHex(m_style->bg_color_regular) CGColor];
|
||||
}
|
||||
self.layer.backgroundColor = bg_color;
|
||||
NSLog(@"debug: button released");
|
||||
|
||||
@ -32,7 +32,7 @@ public:
|
||||
void Play();
|
||||
void Pause();
|
||||
void TogglePause();
|
||||
void ChangeVolume(int new_value);
|
||||
void ChangeVolume(CGFloat new_value);
|
||||
void ToggleMute();
|
||||
bool SetMedia(const std::wstring& media_path);
|
||||
void Stop();
|
||||
|
||||
@ -59,8 +59,8 @@ void CPlayerView::TogglePause() {
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerView::ChangeVolume(int new_value) {
|
||||
// TODO
|
||||
void CPlayerView::ChangeVolume(CGFloat new_value) {
|
||||
m_player.volume = new_value;
|
||||
}
|
||||
|
||||
void CPlayerView::ToggleMute() {
|
||||
|
||||
@ -3,8 +3,17 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface NSVideoSlider : NSSlider
|
||||
#import "footerskin.h"
|
||||
|
||||
@interface NSStyledSlider : NSSlider
|
||||
- (instancetype)initWithStyle:(CSliderStyle*)style;
|
||||
- (void)dealloc;
|
||||
|
||||
// slider appearance
|
||||
- (void)updateStyle;
|
||||
|
||||
// test action function
|
||||
- (void)sliderValueChanged:(NSSlider*)sender;
|
||||
@end
|
||||
|
||||
#endif // VIDEOPLAYER_SLIDER_H_
|
||||
|
||||
@ -0,0 +1,147 @@
|
||||
#import "slider.h"
|
||||
|
||||
#import "utils.h"
|
||||
|
||||
@interface NSStyledSliderCell : NSSliderCell
|
||||
{
|
||||
CSliderStyle* m_style;
|
||||
NSImage* m_knob_image;
|
||||
NSRect m_track_rect;
|
||||
}
|
||||
- (instancetype)initWithStyle:(CSliderStyle*)style;
|
||||
- (void)updateStyle;
|
||||
@end
|
||||
|
||||
@implementation NSStyledSliderCell
|
||||
|
||||
- (instancetype)initWithStyle:(CSliderStyle*)style {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// set skin
|
||||
m_style = style;
|
||||
[self updateStyle];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)drawBarInside:(NSRect)rect flipped:(BOOL)flipped {
|
||||
// draw the whole track
|
||||
const CGFloat track_thickness = m_style->track.thickness;
|
||||
const CGFloat track_border_radius = m_style->track.border_radius;
|
||||
m_track_rect = NSInsetRect(rect, 0, (rect.size.height - track_thickness) / 2);
|
||||
NSBezierPath* track_path = [NSBezierPath bezierPathWithRoundedRect:m_track_rect xRadius:track_border_radius yRadius:track_border_radius];
|
||||
[NSColorFromHex(m_style->track.color) setFill];
|
||||
[track_path fill];
|
||||
// draw the filled portion of track (left of knob)
|
||||
double value = (self.doubleValue - self.minValue) / (self.maxValue - self.minValue);
|
||||
NSRect filled_rect = m_track_rect;
|
||||
filled_rect.size.width *= value;
|
||||
[NSColorFromHex(m_style->track.fill_color) setFill];
|
||||
// TODO: when knob is visible, the right part of the filled rect does not have to be rounded
|
||||
NSBezierPath* filled_path = [NSBezierPath bezierPathWithRoundedRect:filled_rect xRadius:track_border_radius yRadius:track_border_radius];
|
||||
[filled_path fill];
|
||||
}
|
||||
|
||||
- (NSRect)knobRectFlipped:(BOOL)flipped {
|
||||
// calculate knob center offset relative to slider current value
|
||||
// by default we stick knob edge to the edge of the slider track
|
||||
CGFloat knob_center_max_offset = m_knob_image.size.width / 2;
|
||||
if (knob_center_max_offset >= m_track_rect.origin.x) {
|
||||
// if the knob is big enough, then stick it to the control rect edge
|
||||
knob_center_max_offset -= m_track_rect.origin.x;
|
||||
}
|
||||
// this formula essentially means the following:
|
||||
// - near the edges the knob will have corresponding offset from slider exact value, to be able to fit into control rect
|
||||
// - at the middle the offset is zero, meaning the knob positioned exactly where slider is
|
||||
// - the offset changes lineary and flips its sign when knob passes the middle point
|
||||
CGFloat knob_center_offset = -(knob_center_max_offset * self.doubleValue) / ((self.maxValue - self.minValue) / 2) + knob_center_max_offset;
|
||||
// get current slider value
|
||||
double value = (self.doubleValue - self.minValue) / (self.maxValue - self.minValue);
|
||||
CGFloat slider_pos = m_track_rect.size.width * value + m_track_rect.origin.x;
|
||||
// create knob rect from the center point
|
||||
CGFloat knob_center_pos = slider_pos + knob_center_offset;
|
||||
NSRect knob_rect = NSMakeRect(knob_center_pos - m_knob_image.size.width / 2, NSMidY(m_track_rect) - m_knob_image.size.height / 2, m_knob_image.size.width, m_knob_image.size.height);
|
||||
return knob_rect;
|
||||
}
|
||||
|
||||
- (void)drawKnob:(NSRect)knob_rect {
|
||||
if (m_style->is_knob_visible) {
|
||||
[m_knob_image drawInRect:knob_rect];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateStyle {
|
||||
// set knob image
|
||||
if (m_style->is_knob_visible) {
|
||||
const CGFloat knob_thickness = m_style->knob.thickness;
|
||||
m_knob_image = [[NSImage imageWithSize:NSMakeSize(knob_thickness, knob_thickness) flipped:NO drawingHandler:^BOOL(NSRect dst_rect) {
|
||||
// TODO: add border
|
||||
const CGFloat border_radius = m_style->knob.border_radius;
|
||||
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:dst_rect xRadius:border_radius yRadius:border_radius];
|
||||
[NSColorFromHex(m_style->knob.color) setFill];
|
||||
[path fill];
|
||||
return YES;
|
||||
}] retain];
|
||||
} else {
|
||||
const CGFloat knob_thickness = m_style->track.thickness;
|
||||
m_knob_image = [[NSImage alloc] initWithSize:NSMakeSize(knob_thickness, knob_thickness)];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
NSLog(@"debug: slider cell deallocated");
|
||||
#if !__has_feature(objc_arc)
|
||||
[m_knob_image release];
|
||||
[super dealloc];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSStyledSlider ()
|
||||
{
|
||||
NSStyledSliderCell* m_cell;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSStyledSlider
|
||||
|
||||
- (void)setNeedsDisplayInRect:(NSRect)invalid_rect {
|
||||
[super setNeedsDisplayInRect:[self bounds]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithStyle:(CSliderStyle*)style {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self setWantsLayer:YES];
|
||||
// set cell
|
||||
m_cell = [[NSStyledSliderCell alloc] initWithStyle:style];
|
||||
[self setCell:m_cell];
|
||||
// set min and max values
|
||||
self.minValue = 0.0;
|
||||
self.maxValue = 100.0;
|
||||
// set action
|
||||
[self setTarget:self];
|
||||
[self setAction:@selector(sliderValueChanged:)];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
NSLog(@"debug: slider deallocated");
|
||||
#if !__has_feature(objc_arc)
|
||||
[m_cell release];
|
||||
[super dealloc];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)updateStyle {
|
||||
[m_cell updateStyle];
|
||||
}
|
||||
|
||||
- (void)sliderValueChanged:(NSSlider*)sender {
|
||||
NSLog(@"debug: slider value changed: %.2f", sender.doubleValue);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#import "footerskin.h"
|
||||
|
||||
@interface NSTimeLabel : NSTextField
|
||||
- (instancetype)initWithSkin:(CFooterSkin*)skin;
|
||||
- (instancetype)initWithStyle:(CTimeLabelStyle*)style;
|
||||
- (void)dealloc;
|
||||
|
||||
// time label appearance and content
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
@interface NSTimeLabel ()
|
||||
{
|
||||
CFooterSkin* m_skin;
|
||||
CTimeLabelStyle* m_style;
|
||||
NSDictionary* m_attributes;
|
||||
NSSize m_bounding_box_size;
|
||||
}
|
||||
@ -12,12 +12,12 @@
|
||||
|
||||
@implementation NSTimeLabel
|
||||
|
||||
- (instancetype)initWithSkin:(CFooterSkin*)skin {
|
||||
- (instancetype)initWithStyle:(CTimeLabelStyle*)style {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self setWantsLayer:YES];
|
||||
// apply skin
|
||||
m_skin = skin;
|
||||
m_style = style;
|
||||
[self updateStyle];
|
||||
// set initial time
|
||||
[self setText:@"00:00:00"];
|
||||
@ -40,18 +40,18 @@
|
||||
|
||||
- (void)updateStyle {
|
||||
// get font
|
||||
CGFloat font_size = m_skin->time_label.font_size;
|
||||
CGFloat font_size = m_style->font_size;
|
||||
NSFont* font = nil;
|
||||
if (m_skin->time_label.font_name.length == 0) {
|
||||
if (m_style->font_name.length == 0) {
|
||||
font = [NSFont systemFontOfSize:font_size];
|
||||
} else {
|
||||
font = [NSFont fontWithName:m_skin->time_label.font_name size:font_size];
|
||||
font = [NSFont fontWithName:m_style->font_name size:font_size];
|
||||
if (!font) {
|
||||
font = [NSFont systemFontOfSize:font_size];
|
||||
}
|
||||
}
|
||||
// get color
|
||||
NSColor* color = NSColorFromHex(m_skin->time_label.color);
|
||||
NSColor* color = NSColorFromHex(m_style->color);
|
||||
// update attributes
|
||||
m_attributes = @{
|
||||
NSFontAttributeName: font,
|
||||
|
||||
Reference in New Issue
Block a user