Merge pull request #148 from Rafostar/popovers-rework

Popovers rework
This commit is contained in:
Rafał Dzięgiel
2021-09-01 17:18:03 +02:00
committed by GitHub
11 changed files with 426 additions and 373 deletions

View File

@@ -5,17 +5,33 @@ scale marks {
radio {
margin-left: -2px;
}
scrolledwindow scrollbar.vertical slider {
min-height: 16px;
}
/* Adwaita is missing osd ListBox */
.playlistrow {
.clapperplaylist row {
border-radius: 5px;
}
.playlistrow {
.clapperplaylist row {
color: @theme_fg_color;
}
.osd .playlist {
.clapperplaylist row button {
margin: 0px;
padding: 0px;
min-width: 28px;
min-height: 28px;
}
.fullscreen.tvmode .clapperplaylist row button {
min-width: 36px;
min-height: 36px;
margin-left: 2px;
margin-right: 2px;
}
.osd .clapperplaylist {
background: none;
}
.osd .playlist row image {
.osd .clapperplaylist row image {
-gtk-icon-shadow: none;
}
.osdheaderbar {
@@ -41,6 +57,9 @@ popover contents {
border-color: transparent;
box-shadow: none;
}
.popoverseparator separator {
background-color: @insensitive_fg_color;
}
/* Rounded corners */
.adwrounded.csd {
@@ -79,25 +98,29 @@ scale trough slider {
font-size: 21px;
font-weight: 500;
}
.adwicons .playercontrols {
.adwicons .clappercontrols {
margin-bottom: -1px;
}
.playercontrols {
.clappercontrols {
margin-left: 2px;
margin-right: 2px;
}
.playercontrols button {
.clappercontrolsbutton {
margin: 3px;
margin-left: 1px;
margin-right: 1px;
}
.fullscreen.tvmode .playercontrols button {
.fullscreen.tvmode .clappercontrolsbutton {
min-width: 32px;
min-height: 32px;
margin: 5px;
margin-left: 3px;
margin-right: 3px;
}
.clappercontrolsbutton.text-button {
padding-left: 4px;
padding-right: 4px;
}
.fullscreen.tvmode button image {
-gtk-icon-shadow: none;
}
@@ -109,7 +132,8 @@ scale trough slider {
min-height: 17px;
}
.fullscreen.tvmode .playercontrols button image {
/* Also affects popover buttons */
.fullscreen.tvmode .clappercontrols button image {
-gtk-icon-size: 24px;
}
.adwicons .playbackicon {
@@ -118,15 +142,12 @@ scale trough slider {
.adwicons.fullscreen.tvmode .playbackicon {
-gtk-icon-size: 28px;
}
.labelbuttonlabel {
margin-left: -4px;
margin-right: -4px;
min-width: 8px;
.clappercontrolsbutton.text-button label {
font-family: 'Cantarell', sans-serif;
font-variant-numeric: tabular-nums;
font-weight: 600;
}
.fullscreen.tvmode .labelbuttonlabel {
.fullscreen.tvmode .clappercontrolsbutton.text-button label {
font-size: 22px;
text-shadow: none;
}
@@ -157,12 +178,6 @@ scale trough slider {
font-variant-numeric: tabular-nums;
}
/* Button Inside Popover */
.popoverbutton {
min-width: 24px;
min-height: 24px;
}
/* Position Scale */
.positionscale {
margin: -2px;
@@ -245,14 +260,14 @@ scale trough slider {
}
/* Elapsed Popover */
.elapsedpopoverbox {
min-width: 260px;
.elapsedpopover {
min-width: 326px;
}
.elapsedpopoverbox box separator {
background: @insensitive_fg_color;
.fullscreen.tvmode .elapsedpopover {
min-width: 448px;
}
.fullscreen.tvmode .elapsedpopoverbox {
min-width: 360px;
.elapsedpopover contents {
padding-bottom: 0px;
}
.speedscale trough highlight {
min-height: 4px;

View File

@@ -1,10 +1,5 @@
const { GObject, Gtk } = imports.gi;
/* Negative values from CSS */
const PopoverOffset = {
DEFAULT: -3,
TVMODE: -5,
};
const Misc = imports.src.misc;
var CustomButton = GObject.registerClass(
class ClapperCustomButton extends Gtk.Button
@@ -22,29 +17,16 @@ class ClapperCustomButton extends Gtk.Button
super._init(opts);
this.isFullscreen = false;
this.add_css_class('flat');
}
setFullscreenMode(isFullscreen)
{
if(this.isFullscreen === isFullscreen)
return;
/* Redraw icon after style class change */
if(this.icon_name)
this.set_icon_name(this.icon_name);
this.isFullscreen = isFullscreen;
this.add_css_class('clappercontrolsbutton');
}
vfunc_clicked()
{
if(!this.isFullscreen)
return;
const clapperWidget = this.get_ancestor(Gtk.Grid);
clapperWidget.revealControls();
if(clapperWidget.isFullscreenMode)
clapperWidget.revealControls();
}
});
@@ -72,79 +54,73 @@ class ClapperIconToggleButton extends CustomButton
}
});
var PopoverButtonBase = GObject.registerClass(
class ClapperPopoverButtonBase extends Gtk.ToggleButton
var PopoverSeparator = GObject.registerClass({
GTypeName: 'ClapperPopoverSeparator',
Template: `file://${Misc.getClapperPath()}/ui/popover-separator.ui`,
InternalChildren: ['middle_label'],
Properties: {
'label': GObject.ParamSpec.string(
'label',
'Middle label',
'Text to set in the middle',
GObject.ParamFlags.WRITABLE,
null
),
}
},
class ClapperPopoverSeparator extends Gtk.Box
{
_init()
_init(opts)
{
super._init({
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER,
can_focus: false,
});
super._init();
this.isFullscreen = false;
this.add_css_class('flat');
if(!opts.label)
this.visible = false;
this.popover = new Gtk.Popover({
position: Gtk.PositionType.TOP,
});
this.popoverBox = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
});
this.popover.set_child(this.popoverBox);
this.popover.set_offset(0, PopoverOffset.DEFAULT);
if(this.isFullscreen)
this.popover.add_css_class('osd');
this.popover.connect('closed', this._onClosed.bind(this));
this.popover.set_parent(this);
this.label = opts.label;
}
setFullscreenMode(isFullscreen)
set label(value)
{
if(this.isFullscreen === isFullscreen)
return;
this._middle_label.label = value || "";
/* Redraw icon after style class change */
if(this.icon_name)
this.set_icon_name(this.icon_name);
if(value)
this.visible = true;
}
});
this.isFullscreen = isFullscreen;
var PopoverButtonBase = GObject.registerClass({
GTypeName: 'ClapperPopoverButtonBase',
},
class ClapperPopoverButtonBase extends Gtk.MenuButton
{
_init(opts = {})
{
super._init(opts);
/* TODO: Fullscreen non-tv mode */
const offset = (isFullscreen)
? PopoverOffset.TVMODE
: PopoverOffset.DEFAULT;
if(opts.icon_name)
this.icon_name = opts.icon_name;
else if(opts.label)
this.label = opts.label;
this.popover.set_offset(0, offset);
this.toggleButton = this.get_first_child();
this.toggleButton.add_css_class('clappercontrolsbutton');
const cssClass = 'osd';
if(isFullscreen === this.popover.has_css_class(cssClass))
return;
const action = (isFullscreen) ? 'add' : 'remove';
this.popover[action + '_css_class'](cssClass);
this.set_create_popup_func(this._onPopoverOpened);
this.popover.connect('closed', this._onPopoverClosed.bind(this));
}
vfunc_toggled()
_onPopoverOpened(self)
{
if(!this.active)
return;
const clapperWidget = self.get_ancestor(Gtk.Grid);
const clapperWidget = this.get_ancestor(Gtk.Grid);
if(this.isFullscreen) {
if(clapperWidget.isFullscreenMode) {
clapperWidget.revealControls();
clapperWidget.isPopoverOpen = true;
}
this.popover.popup();
}
_onClosed()
_onPopoverClosed(popover)
{
const clapperWidget = this.get_ancestor(Gtk.Grid);
@@ -153,94 +129,107 @@ class ClapperPopoverButtonBase extends Gtk.ToggleButton
clapperWidget.revealControls();
clapperWidget.isPopoverOpen = false;
this.active = false;
}
_onCloseRequest()
{
this.popover.unparent();
}
});
var IconPopoverButton = GObject.registerClass(
class ClapperIconPopoverButton extends PopoverButtonBase
var ElapsedTimeButton = GObject.registerClass({
GTypeName: 'ClapperElapsedTimeButton',
Template: `file://${Misc.getClapperPath()}/ui/elapsed-time-button.ui`,
Children: ['scrolledWindow', 'speedScale'],
},
class ClapperElapsedTimeButton extends PopoverButtonBase
{
_init(icon)
_init(opts)
{
super._init();
super._init(opts);
this.icon_name = icon;
}
});
this.setInitialState();
this.popover.add_css_class('elapsedpopover');
var LabelPopoverButton = GObject.registerClass(
class ClapperLabelPopoverButton extends PopoverButtonBase
{
_init(text)
{
super._init();
this.customLabel = new Gtk.Label({
label: text,
single_line_mode: true,
});
this.customLabel.add_css_class('labelbuttonlabel');
this.set_child(this.customLabel);
this.scrolledWindow.max_content_height = 150;
}
set_label(text)
set label(value)
{
this.customLabel.set_text(text);
}
});
var ElapsedPopoverButton = GObject.registerClass(
class ClapperElapsedPopoverButton extends LabelPopoverButton
{
_init(text)
{
super._init(text);
this.popoverBox.add_css_class('elapsedpopoverbox');
this.scrolledWindow = new Gtk.ScrolledWindow({
max_content_height: 150,
propagate_natural_height: true,
});
this.popoverBox.append(this.scrolledWindow);
this.toggleButton.label = value;
}
setFullscreenMode(isFullscreen)
get label()
{
super.setFullscreenMode(isFullscreen);
return this.toggleButton.label;
}
this.scrolledWindow.max_content_height = (isFullscreen)
setInitialState()
{
this.label = '00:00/00:00';
}
setFullscreenMode(isFullscreen, isMobileMonitor)
{
this.scrolledWindow.max_content_height = (isFullscreen && !isMobileMonitor)
? 190 : 150;
}
});
addSeparator(text)
var TrackSelectButton = GObject.registerClass({
GTypeName: 'ClapperTrackSelectButton',
Template: `file://${Misc.getClapperPath()}/ui/track-select-button.ui`,
Children: ['popoverBox'],
InternalChildren: ['scrolled_window', 'decoder_separator'],
},
class ClapperTrackSelectButton extends PopoverButtonBase
{
_init(opts)
{
const box = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true,
});
const label = new Gtk.Label({
label: text,
halign: Gtk.Align.CENTER,
});
const leftSeparator = new Gtk.Separator({
orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true,
valign: Gtk.Align.CENTER,
});
const rightSeparator = new Gtk.Separator({
orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true,
valign: Gtk.Align.CENTER,
});
box.append(leftSeparator);
box.append(label);
box.append(rightSeparator);
this.popoverBox.append(box);
super._init(opts);
this._scrolled_window.max_content_height = 220;
}
setFullscreenMode(isFullscreen, isMobileMonitor)
{
this._scrolled_window.max_content_height = (isFullscreen && !isMobileMonitor)
? 290 : 220;
}
setDecoder(decoder)
{
this._decoder_separator.label = _('Decoder: %s').format(decoder);
}
});
var VolumeButton = GObject.registerClass({
GTypeName: 'ClapperVolumeButton',
Template: `file://${Misc.getClapperPath()}/ui/volume-button.ui`,
Children: ['volumeScale'],
},
class ClapperVolumeButton extends PopoverButtonBase
{
_onVolumeScaleValueChanged(scale)
{
const volume = scale.get_value();
const cssClass = 'overamp';
const hasOveramp = (scale.has_css_class(cssClass));
if(volume > 1) {
if(!hasOveramp)
scale.add_css_class(cssClass);
}
else {
if(hasOveramp)
scale.remove_css_class(cssClass);
}
const icon = (volume <= 0)
? 'muted'
: (volume <= 0.3)
? 'low'
: (volume <= 0.7)
? 'medium'
: (volume <= 1)
? 'high'
: 'overamplified';
this.icon_name = `audio-volume-${icon}-symbolic`;
}
});

246
src/controls.js vendored
View File

@@ -29,15 +29,29 @@ class ClapperControls extends Gtk.Box
this.showHours = false;
this.durationFormatted = '00:00';
this.buttonsArr = [];
this.revealersArr = [];
this.chapters = null;
this.chapterShowId = null;
this.chapterHideId = null;
this._addTogglePlayButton();
this._addElapsedButton();
this.togglePlayButton = new Buttons.IconToggleButton(
'media-playback-start-symbolic',
'media-playback-pause-symbolic'
);
this.togglePlayButton.child.add_css_class('playbackicon');
this.togglePlayButton.connect(
'clicked', this._onTogglePlayClicked.bind(this)
);
this.append(this.togglePlayButton);
const elapsedRevealer = new Revealers.ButtonsRevealer('SLIDE_RIGHT');
this.elapsedButton = new Buttons.ElapsedTimeButton();
elapsedRevealer.append(this.elapsedButton);
elapsedRevealer.reveal_child = true;
this.append(elapsedRevealer);
this.revealersArr.push(elapsedRevealer);
this._addPositionScale();
const revealTracksButton = new Buttons.IconToggleButton(
@@ -45,30 +59,29 @@ class ClapperControls extends Gtk.Box
'go-next-symbolic'
);
revealTracksButton.add_css_class('narrowbutton');
this.buttonsArr.push(revealTracksButton);
const tracksRevealer = new Revealers.ButtonsRevealer(
'SLIDE_LEFT', revealTracksButton
);
this.visualizationsButton = this.addIconPopoverButton(
'display-projector-symbolic',
tracksRevealer
);
this.visualizationsButton.set_visible(false);
this.videoTracksButton = this.addIconPopoverButton(
'emblem-videos-symbolic',
tracksRevealer
);
this.videoTracksButton.set_visible(false);
this.audioTracksButton = this.addIconPopoverButton(
'emblem-music-symbolic',
tracksRevealer
);
this.audioTracksButton.set_visible(false);
this.subtitleTracksButton = this.addIconPopoverButton(
'media-view-subtitles-symbolic',
tracksRevealer
);
this.subtitleTracksButton.set_visible(false);
this.visualizationsButton = new Buttons.TrackSelectButton({
icon_name: 'display-projector-symbolic',
visible: false,
});
tracksRevealer.append(this.visualizationsButton);
this.videoTracksButton = new Buttons.TrackSelectButton({
icon_name: 'emblem-videos-symbolic',
visible: false,
});
tracksRevealer.append(this.videoTracksButton);
this.audioTracksButton = new Buttons.TrackSelectButton({
icon_name: 'emblem-music-symbolic',
visible: false,
});
tracksRevealer.append(this.audioTracksButton);
this.subtitleTracksButton = new Buttons.TrackSelectButton({
icon_name: 'media-view-subtitles-symbolic',
visible: false,
});
tracksRevealer.append(this.subtitleTracksButton);
this.revealTracksRevealer = new Revealers.ButtonsRevealer('SLIDE_LEFT');
this.revealTracksRevealer.append(revealTracksButton);
@@ -79,24 +92,30 @@ class ClapperControls extends Gtk.Box
this.revealersArr.push(tracksRevealer);
this.append(tracksRevealer);
this._addVolumeButton();
this.unfullscreenButton = this.addButton(
'view-restore-symbolic'
);
this.volumeButton = new Buttons.VolumeButton();
this.append(this.volumeButton);
this.unfullscreenButton = new Buttons.CustomButton({
icon_name: 'view-restore-symbolic',
});
this.unfullscreenButton.connect('clicked', this._onUnfullscreenClicked.bind(this));
this.unfullscreenButton.set_visible(false);
this.append(this.unfullscreenButton);
this.add_css_class('playercontrols');
this.add_css_class('clappercontrols');
this.realizeSignal = this.connect('realize', this._onRealize.bind(this));
}
setFullscreenMode(isFullscreen)
setFullscreenMode(isFullscreen, isMobileMonitor)
{
/* Allow recheck on next resize */
this.isMobile = null;
for(let button of this.buttonsArr)
button.setFullscreenMode(isFullscreen);
this.elapsedButton.setFullscreenMode(isFullscreen, isMobileMonitor);
this.visualizationsButton.setFullscreenMode(isFullscreen, isMobileMonitor);
this.videoTracksButton.setFullscreenMode(isFullscreen, isMobileMonitor);
this.audioTracksButton.setFullscreenMode(isFullscreen, isMobileMonitor);
this.subtitleTracksButton.setFullscreenMode(isFullscreen, isMobileMonitor);
this.unfullscreenButton.visible = isFullscreen;
this.isFullscreen = isFullscreen;
@@ -105,7 +124,7 @@ class ClapperControls extends Gtk.Box
setLiveMode(isLive, isSeekable)
{
if(isLive)
this.elapsedButton.set_label('LIVE');
this.elapsedButton.label = 'LIVE';
this.positionScale.visible = isSeekable;
}
@@ -116,7 +135,7 @@ class ClapperControls extends Gtk.Box
this.positionScale.set_value(0);
this.positionScale.visible = false;
this.elapsedButton.set_label(INITIAL_ELAPSED);
this.elapsedButton.setInitialState();
this.togglePlayButton.setPrimaryIcon();
for(let type of ['video', 'audio', 'subtitle'])
@@ -132,46 +151,7 @@ class ClapperControls extends Gtk.Box
const elapsed = Misc.getFormattedTime(value, this.showHours)
+ '/' + this.durationFormatted;
this.elapsedButton.set_label(elapsed);
}
addButton(buttonIcon, revealer)
{
const button = (buttonIcon instanceof Gtk.Button)
? buttonIcon
: new Buttons.CustomButton({ icon_name: buttonIcon });
if(!revealer)
this.append(button);
else
revealer.append(button);
this.buttonsArr.push(button);
return button;
}
addIconPopoverButton(iconName, revealer)
{
const button = new Buttons.IconPopoverButton(iconName);
return this.addButton(button, revealer);
}
addLabelPopoverButton(text, revealer)
{
text = text || '';
const button = new Buttons.LabelPopoverButton(text);
return this.addButton(button, revealer);
}
addElapsedPopoverButton(text, revealer)
{
text = text || '';
const button = new Buttons.ElapsedPopoverButton(text);
return this.addButton(button, revealer);
this.elapsedButton.label = elapsed;
}
addCheckButtons(box, array, activeId)
@@ -285,51 +265,6 @@ class ClapperControls extends Gtk.Box
}
}
_addTogglePlayButton()
{
this.togglePlayButton = new Buttons.IconToggleButton(
'media-playback-start-symbolic',
'media-playback-pause-symbolic'
);
this.togglePlayButton.child.add_css_class('playbackicon');
this.togglePlayButton.connect(
'clicked', this._onTogglePlayClicked.bind(this)
);
this.addButton(this.togglePlayButton);
}
_addElapsedButton()
{
const elapsedRevealer = new Revealers.ButtonsRevealer('SLIDE_RIGHT');
this.elapsedButton = this.addElapsedPopoverButton(INITIAL_ELAPSED, elapsedRevealer);
elapsedRevealer.set_reveal_child(true);
this.revealersArr.push(elapsedRevealer);
this.elapsedButton.addSeparator('Speed');
const speedScale = new Gtk.Scale({
orientation: Gtk.Orientation.HORIZONTAL,
value_pos: Gtk.PositionType.BOTTOM,
draw_value: false,
round_digits: 2,
hexpand: true,
valign: Gtk.Align.CENTER,
});
speedScale.add_css_class('speedscale');
this.speedAdjustment = speedScale.get_adjustment();
this.speedAdjustment.set_lower(0.01);
this.speedAdjustment.set_upper(2);
this.speedAdjustment.set_value(1);
this.speedAdjustment.set_page_increment(0.1);
speedScale.add_mark(0.25, Gtk.PositionType.BOTTOM, '0.25x');
speedScale.add_mark(1, Gtk.PositionType.BOTTOM, 'Normal');
speedScale.add_mark(2, Gtk.PositionType.BOTTOM, '2x');
this.elapsedButton.popoverBox.append(speedScale);
this.append(elapsedRevealer);
}
_addPositionScale()
{
this.positionScale = new Gtk.Scale({
@@ -381,36 +316,6 @@ class ClapperControls extends Gtk.Box
this.append(box);
}
_addVolumeButton()
{
this.volumeButton = this.addIconPopoverButton(
'audio-volume-muted-symbolic'
);
this.volumeScale = new Gtk.Scale({
orientation: Gtk.Orientation.VERTICAL,
inverted: true,
value_pos: Gtk.PositionType.TOP,
draw_value: false,
vexpand: true,
});
this.volumeScale.add_css_class('volumescale');
this.volumeAdjustment = this.volumeScale.get_adjustment();
this.volumeAdjustment.set_upper(Misc.maxVolume);
this.volumeAdjustment.set_step_increment(0.05);
this.volumeAdjustment.set_page_increment(0.05);
for(let i of [0, 1, Misc.maxVolume]) {
const text = (!i) ? '0%' : (i % 1 === 0) ? `${i}00%` : `${i * 10}0%`;
this.volumeScale.add_mark(i, Gtk.PositionType.LEFT, text);
}
this.volumeScale.connect(
'value-changed', this._onVolumeScaleValueChanged.bind(this)
);
this.volumeButton.popoverBox.append(this.volumeScale);
}
_setChapterVisible(isVisible)
{
const type = (isVisible) ? 'Show' : 'Hide';
@@ -553,42 +458,6 @@ class ClapperControls extends Gtk.Box
}
}
_onVolumeScaleValueChanged(scale)
{
const volume = scale.get_value();
/* FIXME: All of below should be placed in 'volume-changed'
* event once we move to message bus API */
const cssClass = 'overamp';
const hasOveramp = (scale.has_css_class(cssClass));
if(volume > 1) {
if(!hasOveramp)
scale.add_css_class(cssClass);
}
else {
if(hasOveramp)
scale.remove_css_class(cssClass);
}
const icon = (volume <= 0)
? 'muted'
: (volume <= 0.3)
? 'low'
: (volume <= 0.7)
? 'medium'
: (volume <= 1)
? 'high'
: 'overamplified';
const iconName = `audio-volume-${icon}-symbolic`;
if(this.volumeButton.icon_name === iconName)
return;
this.volumeButton.icon_name = iconName;
debug(`set volume icon: ${icon}`);
}
_onPositionScaleDragging(scale)
{
const isPositionDragging = scale.has_css_class('dragging');
@@ -638,13 +507,6 @@ class ClapperControls extends Gtk.Box
this.positionScale.disconnect(this.positionScaleValueSignal);
this.positionScale.disconnect(this.positionScaleDragSignal);
for(let button of this.buttonsArr) {
if(!button._onCloseRequest)
continue;
button._onCloseRequest();
}
this.chapterPopover.unparent();
}
});

View File

@@ -3,6 +3,7 @@ imports.gi.versions.Gtk = '4.0';
imports.gi.versions.Soup = '2.4';
pkg.initGettext();
pkg.initFormat();
const { GstClapper, Gtk, Adw } = imports.gi;
const { App } = imports.src.app;

View File

@@ -354,9 +354,9 @@ class ClapperPlayer extends GstClapper.Clapper
const { controls } = this.widget.get_ancestor(Gtk.Grid);
const value = (isIncrease) ? offset : -offset;
const volume = controls.volumeScale.get_value() + value;
const scale = controls.volumeButton.volumeScale;
controls.volumeScale.set_value(volume);
scale.set_value(scale.get_value() + value);
}
next_chapter()

View File

@@ -28,7 +28,7 @@ class ClapperPlaylistWidget extends Gtk.ListBox
});
this.activeRowId = -1;
this.repeatMode = RepeatMode.NONE;
this.add_css_class('playlist');
this.add_css_class('clapperplaylist');
this.connect('row-activated', this._onRowActivated.bind(this));
}
@@ -255,7 +255,6 @@ class ClapperPlaylistItem extends Gtk.ListBoxRow
}
this.filename = filename || uri;
this.set_tooltip_text(this.filename);
this.add_css_class('playlistrow');
const box = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
@@ -270,7 +269,6 @@ class ClapperPlaylistItem extends Gtk.ListBoxRow
});
repeatButton.add_css_class('flat');
repeatButton.add_css_class('circular');
repeatButton.add_css_class('popoverbutton');
repeatButton.connect('clicked', this._onRepeatClicked.bind(this));
const label = new Gtk.Label({
label: this.filename,
@@ -285,7 +283,6 @@ class ClapperPlaylistItem extends Gtk.ListBoxRow
});
removeButton.add_css_class('flat');
removeButton.add_css_class('circular');
removeButton.add_css_class('popoverbutton');
removeButton.connect('clicked', this._onRemoveClicked.bind(this));
box.append(repeatButton);

View File

@@ -65,16 +65,23 @@ class ClapperWidget extends Gtk.Grid
this.controls.elapsedButton.scrolledWindow.set_child(this.player.playlistWidget);
this.controls.speedAdjustment.bind_property(
const speedAdjustment = this.controls.elapsedButton.speedScale.get_adjustment();
speedAdjustment.bind_property(
'value', this.player, 'rate', GObject.BindingFlags.BIDIRECTIONAL
);
this.controls.volumeAdjustment.bind_property(
const volumeAdjustment = this.controls.volumeButton.volumeScale.get_adjustment();
volumeAdjustment.bind_property(
'value', this.player, 'volume', GObject.BindingFlags.BIDIRECTIONAL
);
this.player.connect('position-updated', this._onPlayerPositionUpdated.bind(this));
this.player.connect('duration-changed', this._onPlayerDurationChanged.bind(this));
this.player.connect('media-info-updated', this._onMediaInfoUpdated.bind(this));
this.player.connect('video-decoder-changed', this._onPlayerVideoDecoderChanged.bind(this));
this.player.connect('audio-decoder-changed', this._onPlayerAudioDecoderChanged.bind(this));
this.overlay.set_child(playerWidget);
this.overlay.add_overlay(this.revealerTop);
this.overlay.add_overlay(this.revealerBottom);
@@ -155,7 +162,7 @@ class ClapperWidget extends Gtk.Grid
this.revealerBottom.revealerBox.visible = isFullscreen;
this._changeControlsPlacement(isFullscreen);
this.controls.setFullscreenMode(isFullscreen);
this.controls.setFullscreenMode(isFullscreen, this.isMobileMonitor);
if(this.revealerTop.child_revealed)
this._checkSetUpdateTimeInterval();
@@ -503,6 +510,16 @@ class ClapperWidget extends Gtk.Grid
this.controls.positionScale.set_value(positionSeconds);
}
_onPlayerVideoDecoderChanged(player, decoder)
{
this.controls.videoTracksButton.setDecoder(decoder);
}
_onPlayerAudioDecoderChanged(player, decoder)
{
this.controls.audioTracksButton.setDecoder(decoder);
}
_onStateNotify(toplevel)
{
const isMaximized = Boolean(

58
ui/elapsed-time-button.ui Normal file
View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ClapperElapsedTimeButton" parent="ClapperPopoverButtonBase">
<property name="popover">popover</property>
<property name="direction">up</property>
<property name="valign">center</property>
<property name="halign">center</property>
<property name="can_focus">False</property>
<style>
<class name="flat"/>
</style>
</template>
<object class="GtkPopover" id="popover">
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkScrolledWindow" id="scrolledWindow">
<property name="propagate_natural_width">False</property>
<property name="propagate_natural_height">True</property>
</object>
</child>
<child>
<object class="ClapperPopoverSeparator">
<property name="label" translatable="yes">Speed</property>
</object>
</child>
<child>
<object class="GtkScale" id="speedScale">
<property name="orientation">horizontal</property>
<property name="value_pos">bottom</property>
<property name="draw_value">False</property>
<property name="round_digits">2</property>
<property name="hexpand">True</property>
<property name="valign">center</property>
<property name="adjustment">speed_adjustment</property>
<marks>
<mark value="0.25" position="bottom">0.25x</mark>
<mark value="1" position="bottom" translatable="yes">Normal</mark>
<mark value="2" position="bottom">2x</mark>
</marks>
<style>
<class name="speedscale"/>
</style>
</object>
</child>
</object>
</child>
</object>
<object class="GtkAdjustment" id="speed_adjustment">
<property name="lower">0.01</property>
<property name="upper">2</property>
<property name="value">1</property>
<property name="page-increment">0.1</property>
</object>
</interface>

29
ui/popover-separator.ui Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ClapperPopoverSeparator" parent="GtkBox">
<property name="orientation">horizontal</property>
<property name="hexpand">True</property>
<style>
<class name="popoverseparator"/>
</style>
<child>
<object class="GtkSeparator">
<property name="orientation">horizontal</property>
<property name="hexpand">True</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkLabel" id="middle_label">
<property name="halign">center</property>
</object>
</child>
<child>
<object class="GtkSeparator">
<property name="orientation">horizontal</property>
<property name="hexpand">True</property>
<property name="valign">center</property>
</object>
</child>
</template>
</interface>

37
ui/track-select-button.ui Normal file
View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ClapperTrackSelectButton" parent="ClapperPopoverButtonBase">
<property name="popover">popover</property>
<property name="direction">up</property>
<property name="valign">center</property>
<property name="halign">center</property>
<property name="can_focus">False</property>
<style>
<class name="flat"/>
</style>
</template>
<object class="GtkPopover" id="popover">
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="ClapperPopoverSeparator" id="decoder_separator">
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolled_window">
<property name="propagate_natural_width">True</property>
<property name="propagate_natural_height">True</property>
<child>
<object class="GtkBox" id="popoverBox">
<property name="orientation">vertical</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

48
ui/volume-button.ui Normal file
View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ClapperVolumeButton" parent="ClapperPopoverButtonBase">
<property name="icon_name">audio-volume-muted-symbolic</property>
<property name="popover">popover</property>
<property name="direction">up</property>
<property name="valign">center</property>
<property name="halign">center</property>
<property name="can_focus">False</property>
<style>
<class name="flat"/>
</style>
</template>
<object class="GtkPopover" id="popover">
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkScale" id="volumeScale">
<property name="orientation">vertical</property>
<property name="inverted">True</property>
<property name="value_pos">top</property>
<property name="draw_value">False</property>
<property name="vexpand">True</property>
<property name="adjustment">volume_adjustment</property>
<signal name="value-changed" handler="_onVolumeScaleValueChanged"/>
<marks>
<mark value="0" position="left">0%</mark>
<mark value="1" position="left">100%</mark>
<mark value="1.5" position="left">150%</mark>
</marks>
<style>
<class name="volumescale"/>
</style>
</object>
</child>
</object>
</child>
</object>
<object class="GtkAdjustment" id="volume_adjustment">
<property name="lower">0</property>
<property name="upper">1.5</property>
<property name="step-increment">0.05</property>
<property name="page-increment">0.05</property>
</object>
</interface>