use gtk::glib::prelude::ObjectExt;
use gtk::prelude::{
BinExt, BoxExt, Cast, ContainerExt, FixedExt, FlowBoxChildExt, FlowBoxExt, GridExt, ListBoxExt,
ListBoxRowExt, StackExt, WidgetExt,
};
use crate::factory::{FactoryView, positions};
impl FactoryView for gtk::Box {
type Children = gtk::Widget;
type ReturnedWidget = gtk::Widget;
type Position = ();
fn factory_remove(&self, widget: &Self::ReturnedWidget) {
self.remove(widget);
}
fn factory_append(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
) -> Self::ReturnedWidget {
self.add(widget.as_ref());
widget.as_ref().clone()
}
fn factory_prepend(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
) -> Self::ReturnedWidget {
self.add(widget.as_ref());
self.reorder_child(widget.as_ref(), 0);
widget.as_ref().clone()
}
fn factory_insert_after(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
other: &Self::ReturnedWidget,
) -> Self::ReturnedWidget {
self.add(widget.as_ref());
let children = self.children();
if let Some(pos) = children.iter().position(|c| c == other) {
self.reorder_child(widget.as_ref(), pos as i32 + 1);
}
widget.as_ref().clone()
}
fn returned_widget_to_child(returned_widget: &Self::ReturnedWidget) -> Self::Children {
returned_widget.clone()
}
fn factory_move_after(&self, widget: &Self::ReturnedWidget, other: &Self::ReturnedWidget) {
let children = self.children();
if let Some(pos) = children.iter().position(|c| c == other) {
self.reorder_child(widget, pos as i32 + 1);
}
}
fn factory_move_start(&self, widget: &Self::ReturnedWidget) {
self.reorder_child(widget, 0);
}
}
impl FactoryView for gtk::Grid {
type Children = gtk::Widget;
type ReturnedWidget = gtk::Widget;
type Position = positions::GridPosition;
fn factory_remove(&self, widget: &Self::ReturnedWidget) {
self.remove(widget);
}
fn factory_append(
&self,
widget: impl AsRef<Self::Children>,
position: &Self::Position,
) -> Self::ReturnedWidget {
self.attach(
widget.as_ref(),
position.column,
position.row,
position.width,
position.height,
);
widget.as_ref().clone()
}
fn factory_prepend(
&self,
widget: impl AsRef<Self::Children>,
position: &Self::Position,
) -> Self::ReturnedWidget {
self.factory_append(widget, position)
}
fn factory_insert_after(
&self,
widget: impl AsRef<Self::Children>,
position: &Self::Position,
_other: &Self::ReturnedWidget,
) -> Self::ReturnedWidget {
self.factory_append(widget, position)
}
fn factory_move_after(&self, _widget: &Self::ReturnedWidget, _other: &Self::ReturnedWidget) {}
fn factory_move_start(&self, _widget: &Self::ReturnedWidget) {}
fn returned_widget_to_child(returned_widget: &Self::ReturnedWidget) -> Self::Children {
returned_widget.clone()
}
fn factory_update_position(&self, widget: &Self::ReturnedWidget, position: &Self::Position) {
self.factory_remove(widget);
self.factory_append(widget, position);
}
}
impl FactoryView for gtk::Fixed {
type ReturnedWidget = gtk::Widget;
type Children = gtk::Widget;
type Position = (f64, f64);
fn factory_remove(&self, widget: &Self::ReturnedWidget) {
self.remove(widget);
}
fn factory_append(
&self,
widget: impl AsRef<Self::Children>,
position: &Self::Position,
) -> Self::ReturnedWidget {
self.put(widget.as_ref(), position.0 as i32, position.1 as i32);
widget.as_ref().clone()
}
fn factory_prepend(
&self,
widget: impl AsRef<Self::Children>,
position: &Self::Position,
) -> Self::ReturnedWidget {
self.factory_append(widget, position)
}
fn factory_insert_after(
&self,
widget: impl AsRef<Self::Children>,
position: &Self::Position,
_other: &Self::ReturnedWidget,
) -> Self::ReturnedWidget {
self.factory_append(widget, position)
}
fn returned_widget_to_child(returned_widget: &Self::ReturnedWidget) -> Self::Children {
returned_widget.clone()
}
fn factory_move_after(&self, _widget: &Self::ReturnedWidget, _other: &Self::ReturnedWidget) {}
fn factory_move_start(&self, _widget: &Self::ReturnedWidget) {}
fn factory_update_position(&self, widget: &Self::ReturnedWidget, position: &Self::Position) {
self.factory_remove(widget);
self.factory_append(widget, position);
}
}
impl FactoryView for gtk::Stack {
type Children = gtk::Widget;
type ReturnedWidget = gtk::Widget;
type Position = ();
fn factory_remove(&self, widget: &Self::ReturnedWidget) {
self.remove(widget);
}
fn factory_append(
&self,
widget: impl AsRef<Self::Children>,
_position: &Self::Position,
) -> Self::ReturnedWidget {
let widget = widget.as_ref();
let name = widget.widget_name();
if !name.is_empty() {
self.add_named(widget, &name);
} else {
self.add(widget);
}
let stack = gtk::glib::clone::Downgrade::downgrade(self);
widget.connect_notify_local(Some("name"), move |widget, _| {
if let Some(stack) = stack.upgrade() {
let name = widget.widget_name();
if !name.is_empty()
&& widget.parent().as_ref() == Some(stack.upcast_ref::<gtk::Widget>())
{
stack.set_child_name(widget, Some(&name));
}
}
});
widget.clone()
}
fn factory_prepend(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
) -> Self::ReturnedWidget {
self.factory_append(widget, &())
}
fn factory_insert_after(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
_other: &Self::ReturnedWidget,
) -> Self::ReturnedWidget {
self.factory_append(widget, &())
}
fn factory_move_after(&self, _widget: &Self::ReturnedWidget, _other: &Self::ReturnedWidget) {}
fn factory_move_start(&self, _widget: &Self::ReturnedWidget) {}
fn returned_widget_to_child(returned_widget: &Self::ReturnedWidget) -> Self::Children {
returned_widget.clone()
}
}
impl FactoryView for gtk::ListBox {
type Children = gtk::Widget;
type ReturnedWidget = gtk::ListBoxRow;
type Position = ();
fn factory_remove(&self, widget: &Self::ReturnedWidget) {
self.remove(widget);
}
fn factory_append(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
) -> Self::ReturnedWidget {
let widget = widget.as_ref();
self.add(widget);
match widget.downcast_ref::<gtk::ListBoxRow>() {
Some(row) => row.clone(),
None => widget.parent().unwrap().downcast().unwrap(),
}
}
fn factory_prepend(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
) -> Self::ReturnedWidget {
let widget = widget.as_ref();
self.prepend(widget);
match widget.downcast_ref::<gtk::ListBoxRow>() {
Some(row) => row.clone(),
None => widget.parent().unwrap().downcast().unwrap(),
}
}
fn factory_insert_after(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
other: &Self::ReturnedWidget,
) -> Self::ReturnedWidget {
let widget = widget.as_ref();
self.insert(widget, other.index() + 1);
match widget.downcast_ref::<gtk::ListBoxRow>() {
Some(row) => row.clone(),
None => widget.parent().unwrap().downcast().unwrap(),
}
}
fn factory_move_after(&self, widget: &Self::ReturnedWidget, other: &Self::ReturnedWidget) {
self.remove(widget);
self.insert(widget, other.index() + 1);
}
fn factory_move_start(&self, widget: &Self::ReturnedWidget) {
self.remove(widget);
self.prepend(widget);
}
fn returned_widget_to_child(returned_widget: &Self::ReturnedWidget) -> Self::Children {
returned_widget
.child()
.unwrap_or_else(|| returned_widget.upcast_ref::<gtk::Widget>().clone())
}
}
impl FactoryView for gtk::FlowBox {
type Children = gtk::Widget;
type ReturnedWidget = gtk::FlowBoxChild;
type Position = ();
fn factory_remove(&self, widget: &Self::ReturnedWidget) {
self.remove(widget);
}
fn factory_append(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
) -> Self::ReturnedWidget {
let widget = widget.as_ref();
self.insert(widget, -1);
match widget.downcast_ref::<gtk::FlowBoxChild>() {
Some(child) => child.clone(),
None => widget.parent().unwrap().downcast().unwrap(),
}
}
fn factory_prepend(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
) -> Self::ReturnedWidget {
let widget = widget.as_ref();
self.insert(widget, 0);
match widget.downcast_ref::<gtk::FlowBoxChild>() {
Some(child) => child.clone(),
None => widget.parent().unwrap().downcast().unwrap(),
}
}
fn factory_insert_after(
&self,
widget: impl AsRef<Self::Children>,
_position: &(),
other: &Self::ReturnedWidget,
) -> Self::ReturnedWidget {
let widget = widget.as_ref();
self.insert(widget, other.index() + 1);
match widget.downcast_ref::<gtk::FlowBoxChild>() {
Some(child) => child.clone(),
None => widget.parent().unwrap().downcast().unwrap(),
}
}
fn factory_move_after(&self, widget: &Self::ReturnedWidget, other: &Self::ReturnedWidget) {
self.remove(widget);
self.insert(widget, other.index() + 1);
}
fn factory_move_start(&self, widget: &Self::ReturnedWidget) {
self.remove(widget);
self.insert(widget, 0);
}
fn returned_widget_to_child(returned_widget: &Self::ReturnedWidget) -> Self::Children {
returned_widget
.child()
.unwrap_or_else(|| returned_widget.upcast_ref::<gtk::Widget>().clone())
}
}