Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions crates/cp-panel/src/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const KEYS_PER_LINE: usize = 56;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Face {
Found,
FoundThumb,
Thumb,
Paint,
Block(i32),
Expand All @@ -52,7 +53,11 @@ pub struct Seen<'a> {
impl Face {
pub fn of(seen: &Seen<'_>) -> Self {
if seen.found {
return Self::Found;
return if seen.thumb {
Self::FoundThumb
} else {
Self::Found
};
}
if seen.thumb {
return Self::Thumb;
Expand All @@ -79,6 +84,7 @@ impl Face {
pub fn as_str(self) -> &'static str {
match self {
Self::Found => "found",
Self::FoundThumb => "found-thumb",
Self::Thumb => "thumb",
Self::Paint => "paint",
Self::Block(_) => "block",
Expand All @@ -100,7 +106,7 @@ impl Face {
pub fn body_px(self) -> f32 {
match self {
Self::Found | Self::Link => LINE,
Self::Thumb => THUMB,
Self::Thumb | Self::FoundThumb => THUMB,
Self::Paint => PAINT,
Self::Block(lines) => BLOCK_PAD + MONO_LINE * lines as f32,
Self::Keys(lines) => KEYS_LINE * lines as f32,
Expand All @@ -110,7 +116,10 @@ impl Face {
}

pub fn shut_px(self) -> f32 {
TOP + META + GAP + self.body_px() + BOTTOM + BETWEEN
match self {
Self::Paint => TOP + META + BOTTOM + BETWEEN,
_ => TOP + META + GAP + self.body_px() + BOTTOM + BETWEEN,
}
}
}

Expand Down Expand Up @@ -200,7 +209,7 @@ pub fn open_body_px(face: Face, opened: &Opened, claims: i32, room: f32) -> f32
GAP + NOTE
};
match face {
Face::Thumb => OPEN_THUMB + GAP + NOTE,
Face::Thumb | Face::FoundThumb => OPEN_THUMB + GAP + NOTE,
Face::Words(_) | Face::Found => LINE * opened.lines as f32 + note,
Face::Block(_) | Face::Keys(_) | Face::Link if claims > 0 => {
BLOCK_PAD + MONO_LINE * claims as f32
Expand Down
14 changes: 14 additions & 0 deletions crates/cp-panel/src/face_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ fn a_search_hit_a_picture_and_a_colour_win_over_the_kind() {
let mut one = seen(Some(Kind::Code), "fn main() {}");
one.found = true;
assert_eq!(Face::of(&one), Face::Found);
one.thumb = true;
assert_eq!(
Face::of(&one),
Face::FoundThumb,
"a picture found by its words keeps its thumbnail"
);
one.found = false;
one.found = false;
one.thumb = true;
assert_eq!(Face::of(&one), Face::Thumb);
Expand Down Expand Up @@ -166,3 +173,10 @@ fn an_open_card_is_as_tall_as_its_body_its_note_and_its_keys() {
TOP + META + GAP + GAP + KEYS_ROW + BOTTOM + BETWEEN
);
}

#[test]
fn a_colour_sits_on_a_single_row_while_closed() {
assert_eq!(Face::Paint.shut_px(), TOP + META + BOTTOM + BETWEEN);
assert_eq!(Face::FoundThumb.body_px(), THUMB);
assert_eq!(Face::FoundThumb.as_str(), "found-thumb");
}
22 changes: 22 additions & 0 deletions crates/cp-panel/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ pub fn card_of(row: &Listed, now: i64, meta: Option<&MetaOfOne>) -> Card {
|| crate::opening::can_open_link(row.kind, &row.preview),
can_drag: crate::dragging::can_drag(row.kind, &paths_of(row)),
paint: shown_as_colour(row).unwrap_or_default(),
paint_said: paint_said(row).into(),
paints: shown_as_colour(row).is_some(),
thumb: slint::Image::default(),
has_thumb: row.thumb_path.is_some(),
Expand Down Expand Up @@ -448,6 +449,27 @@ pub fn shown_as_colour(row: &Listed) -> Option<slint::Color> {
))
}

pub fn paint_said(row: &Listed) -> String {
let Some(said) = row
.kind
.filter(|kind| *kind == Kind::Color)
.and_then(|_| cp_core::paint::rgba_of(row.preview.lines().next()?))
else {
return String::new();
};
if said.alpha == 255 {
format!("rgb({}, {}, {})", said.red, said.green, said.blue)
} else {
format!(
"rgba({}, {}, {}, {:.2})",
said.red,
said.green,
said.blue,
f32::from(said.alpha) / 255.0
)
}
}

pub fn squeezed_of(text: &str) -> String {
let mut out = String::with_capacity(text.len());
let mut spaced = true;
Expand Down
10 changes: 10 additions & 0 deletions crates/cp-panel/src/view_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -920,3 +920,13 @@ fn a_hit_inside_a_text_of_many_lines_is_shown_on_one() {
assert_eq!(tail, " gesto que en o… </article> ");
assert!(![lead, hit, tail].concat().contains('\n'));
}

#[test]
fn a_colour_says_its_channels_and_anything_else_says_nothing() {
let mut colour = row(Some(Kind::Color));
colour.preview = "#FF8800".into();
assert_eq!(paint_said(&colour), "rgb(255, 136, 0)");
colour.preview = "#FF880080".into();
assert_eq!(paint_said(&colour), "rgba(255, 136, 0, 0.50)");
assert_eq!(paint_said(&row(Some(Kind::Text))), "");
}
94 changes: 61 additions & 33 deletions crates/cp-panel/ui/cards.slint
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ export component Action inherits Rectangle {
in property <image> icon;
in property <color> hot: Theme.body;
in property <bool> awake: true;
in property <bool> marked;
callback pressed();
width: 22px;
height: 22px;
border-radius: 6px;
background: touch.has-hover ? #333853 : transparent;
background: touch.has-hover ? #333853 : root.marked ? Theme.tile : transparent;
animate background { duration: 100ms; }
Icon { source: root.icon; width: 14px; height: 14px; tint: touch.has-hover ? root.hot : Theme.muted; }
Icon { source: root.icon; width: 14px; height: 14px; tint: touch.has-hover ? root.hot : root.marked ? Theme.accent-dim : Theme.muted; }
touch := TouchArea {
enabled: root.awake;
clicked => { root.pressed(); }
Expand Down Expand Up @@ -247,12 +248,20 @@ component KeyChip inherits Rectangle {
in property <string> keys;
in property <string> says;
in property <bool> on;
callback pressed();
accessible-role: AccessibleRole.button;
accessible-label: root.says;
height: 22px;
width: chip-row.preferred-width;
border-radius: 6px;
background: on ? Theme.selected : Theme.field;
background: touch.has-hover ? Theme.row-hover : on ? Theme.selected : Theme.field;
animate background { duration: 100ms; }
border-width: 1px;
border-color: on ? Theme.selected-edge : Theme.field-border;
border-color: on || touch.has-hover ? Theme.selected-edge : Theme.field-border;
touch := TouchArea {
mouse-cursor: MouseCursor.pointer;
clicked => { root.pressed(); }
}
chip-row := HorizontalLayout {
padding-left: 8px;
padding-right: 8px;
Expand Down Expand Up @@ -282,6 +291,8 @@ export component CardView inherits Rectangle {
callback copy(int);
callback open-asked(int);
callback forms(int);
callback paste(int);
callback plain(int);
callback edit(int);
callback named(int, string);
callback naming-dropped();
Expand Down Expand Up @@ -360,7 +371,25 @@ export component CardView inherits Rectangle {
max-width: 180px;
vertical-alignment: center;
}
if !one-kind : Text {
if card.face == "paint" : Rectangle {
width: 18px;
height: 18px;
y: (parent.height - 18px) / 2;
border-radius: 5px;
background: card.paint;
border-width: 1px;
border-color: Theme.selected-edge;
}
if card.face == "paint" : Text {
text: card.squeezed;
color: Theme.body;
font-size: 13px;
font-family: "Cascadia Mono";
overflow: elide;
wrap: no-wrap;
vertical-alignment: center;
}
if !one-kind && card.face != "paint" : Text {
text: card.title;
color: Hue.of(card.kind);
font-size: 11px;
Expand Down Expand Up @@ -420,7 +449,7 @@ export component CardView inherits Rectangle {
if card.can-open && !card.broken : Action { icon: @image-url("../assets/icons/external-link.svg"); says: Words.open-it; pressed => { root.open-asked(card.id); } }
Action { icon: @image-url("../assets/icons/pencil.svg"); says: Words.name-it; pressed => { root.edit(card.id); } }
if !card.broken : Action { icon: @image-url("../assets/icons/copy.svg"); says: Words.copy-it; pressed => { root.copy(card.id); } }
if !card.broken : Action { icon: @image-url("../assets/icons/arrow-right-to-line.svg"); says: Words.paste-as; pressed => { root.forms(card.id); } }
if !card.broken : Action { icon: @image-url("../assets/icons/arrow-right-to-line.svg"); says: Words.paste-as; marked: true; pressed => { root.forms(card.id); } }
Action { icon: card.pinned ? @image-url("../assets/icons/pin-off.svg") : @image-url("../assets/icons/pin.svg"); says: card.pinned ? Words.unpin : Words.pin; pressed => { root.pin(card.id, !card.pinned); } }
Action { icon: @image-url("../assets/icons/trash-2.svg"); says: Words.remove; hot: Theme.danger; pressed => { root.remove(card.id); } }
}
Expand Down Expand Up @@ -471,26 +500,25 @@ export component CardView inherits Rectangle {
}
}

if !open && card.face == "paint" : HorizontalLayout {
height: 24px;
spacing: 10px;
if !open && card.face == "found-thumb" : HorizontalLayout {
height: 50px;
spacing: 12px;
Rectangle {
width: 24px;
height: 24px;
border-radius: 6px;
background: card.paint;
border-width: 1px;
border-color: Theme.selected-edge;
width: 50px;
height: 50px;
border-radius: 7px;
clip: true;
background: Theme.tile;
Image { source: card.thumb; width: parent.width; height: parent.height; image-fit: cover; }
}
Text {
text: card.squeezed;
color: Theme.body;
font-size: 13px;
font-family: "Cascadia Mono";
overflow: elide;
wrap: no-wrap;
horizontal-stretch: 1;
vertical-alignment: center;
VerticalLayout {
alignment: center;
HorizontalLayout {
height: 19px;
Text { text: card.lead; color: Theme.muted; font-size: 13.5px; vertical-alignment: center; }
Text { text: card.hit; color: Theme.accent; font-size: 13.5px; font-weight: 700; vertical-alignment: center; }
Text { text: card.tail; color: Theme.body; font-size: 13.5px; overflow: elide; horizontal-stretch: 1; vertical-alignment: center; }
}
}
}

Expand Down Expand Up @@ -576,14 +604,14 @@ export component CardView inherits Rectangle {
overflow: elide;
}

if open && card.face == "thumb" : Rectangle {
if open && (card.face == "thumb" || card.face == "found-thumb") : Rectangle {
height: 146px;
border-radius: 8px;
clip: true;
background: Theme.tile;
Image { source: card.thumb; width: parent.width; height: parent.height; image-fit: contain; }
}
if open && card.face == "thumb" : Text {
if open && (card.face == "thumb" || card.face == "found-thumb") : Text {
height: 15px;
text: card.media-measures != "" ? card.media-measures : card.headline;
color: Theme.muted;
Expand Down Expand Up @@ -651,9 +679,9 @@ export component CardView inherits Rectangle {
border-color: Theme.selected-edge;
}
Text {
text: card.squeezed;
color: Theme.body;
font-size: 14px;
text: card.paint-said;
color: Theme.muted;
font-size: 13px;
font-family: "Cascadia Mono";
vertical-alignment: center;
overflow: elide;
Expand All @@ -668,9 +696,9 @@ export component CardView inherits Rectangle {
if open && !card.broken : HorizontalLayout {
height: 22px;
spacing: 6px;
KeyChip { keys: "⏎"; says: Words.paste-it; on: true; }
KeyChip { keys: "⇧⏎"; says: Words.paste-plain; }
KeyChip { keys: Theme.apple ? "⌥⏎" : "Alt ⏎"; says: Words.paste-as-short; }
KeyChip { keys: "⏎"; says: Words.paste-it; on: true; pressed => { root.paste(card.id); } }
KeyChip { keys: "⇧⏎"; says: Words.paste-plain; pressed => { root.plain(card.id); } }
KeyChip { keys: Theme.apple ? "⌥⏎" : "Alt ⏎"; says: Words.paste-as-short; pressed => { root.forms(card.id); } }
Rectangle { horizontal-stretch: 1; }
}
}
Expand Down Expand Up @@ -830,7 +858,7 @@ export component CardView inherits Rectangle {
if card.can-open && !card.broken : Action { icon: @image-url("../assets/icons/external-link.svg"); says: Words.open-it; awake: lit; pressed => { root.open-asked(card.id); } }
Action { icon: @image-url("../assets/icons/pencil.svg"); says: Words.name-it; awake: lit; pressed => { root.edit(card.id); } }
if !card.broken : Action { icon: @image-url("../assets/icons/copy.svg"); says: Words.copy-it; awake: lit; pressed => { root.copy(card.id); } }
if !card.broken : Action { icon: @image-url("../assets/icons/arrow-right-to-line.svg"); says: Words.paste-as; awake: lit; pressed => { root.forms(card.id); } }
if !card.broken : Action { icon: @image-url("../assets/icons/arrow-right-to-line.svg"); says: Words.paste-as; awake: lit; marked: true; pressed => { root.forms(card.id); } }
Action { icon: card.pinned ? @image-url("../assets/icons/pin-off.svg") : @image-url("../assets/icons/pin.svg"); says: card.pinned ? Words.unpin : Words.pin; awake: lit; pressed => { root.pin(card.id, !card.pinned); } }
Action { icon: @image-url("../assets/icons/trash-2.svg"); says: Words.remove; hot: Theme.danger; awake: lit; pressed => { root.remove(card.id); } }
}
Expand Down
2 changes: 2 additions & 0 deletions crates/cp-panel/ui/panel.slint
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,8 @@ export component Panel inherits Window {
}
layout: root.layout;
copy(id) => { root.copy(id); }
paste(id) => { root.paste(id); }
plain(id) => { root.paste-as(id, "plain-text"); }
forms(id) => {
root.current = index;
root.opened = false;
Expand Down
1 change: 1 addition & 0 deletions crates/cp-panel/ui/types.slint
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export struct Card {
open-px: length,
mono: bool,
paint: color,
paint-said: string,
paints: bool,
can-open: bool,
can-drag: bool,
Expand Down
Loading