Skip to content

Commit

Permalink
Show coordinate on hover
Browse files Browse the repository at this point in the history
  • Loading branch information
cmyr committed May 26, 2020
1 parent 13c9c70 commit 446ba2c
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 14 deletions.
7 changes: 7 additions & 0 deletions src/app_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ impl AppDelegate<AppState> for Delegate {
false
}

consts::cmd::TOGGLE_COORDINATE_HOVER => {
let current_val = data.workspace.settings().show_coordinate_on_hover;
data.workspace.settings_mut().show_coordinate_on_hover = !current_val;
ctx.submit_command(consts::cmd::REBUILD_MENUS, None);
false
}

consts::cmd::NEW_GLYPH => {
let new_glyph_name = data.workspace.add_new_glyph();
data.workspace.selected = Some(new_glyph_name);
Expand Down
3 changes: 3 additions & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ pub mod cmd {
/// The arguments **must** be a `ToggleGuideCmdArgs`.
pub const TOGGLE_GUIDE: Selector = Selector::new("runebender.toggle-guide");

pub const TOGGLE_COORDINATE_HOVER: Selector =
Selector::new("runebender.toggle-coordinate-hover");

/// Arguments passed along with the TOGGLE_GUIDE command
pub struct ToggleGuideCmdArgs {
pub id: EntityId,
Expand Down
21 changes: 21 additions & 0 deletions src/data.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Application state.
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
use std::error::Error;
use std::fs;
Expand Down Expand Up @@ -28,6 +29,7 @@ pub struct AppState {
/// A workspace is a single font, corresponding to a UFO file on disk.
#[derive(Clone, Lens, Data, Default)]
pub struct Workspace {
pub shared_settings: SharedSettings,
pub font: Arc<FontObject>,
/// The currently selected glyph (in the main glyph list) if any.
//TODO: allow multiple selections
Expand All @@ -39,6 +41,14 @@ pub struct Workspace {
pub info: SimpleFontInfo,
}

/// Global application preferences
#[derive(Clone, Debug, Default, Data, Lens)]
pub struct Settings {
pub show_coordinate_on_hover: bool,
}

pub type SharedSettings = Arc<RefCell<Settings>>;

#[derive(Clone, Data)]
pub struct FontObject {
pub path: Option<Arc<Path>>,
Expand Down Expand Up @@ -81,6 +91,7 @@ pub struct FontMetrics {
/// The state for an editor view.
#[derive(Clone, Data, Lens)]
pub struct EditorState {
pub settings: SharedSettings,
pub metrics: FontMetrics,
pub font: Workspace,
pub session: Arc<EditSession>,
Expand Down Expand Up @@ -276,6 +287,14 @@ impl Workspace {
pub fn font_mut(&mut self) -> &mut FontObject {
Arc::make_mut(&mut self.font)
}

pub fn settings_mut(&mut self) -> RefMut<Settings> {
self.shared_settings.borrow_mut()
}

pub fn settings(&self) -> Ref<Settings> {
self.shared_settings.borrow()
}
}

impl GlyphPlus {
Expand Down Expand Up @@ -485,6 +504,7 @@ pub mod lenses {
let metrics = data.info.metrics.clone();
let session = data.sessions.get(&self.0).cloned().unwrap();
let glyph = EditorState_ {
settings: data.shared_settings.clone(),
font: data.clone(),
metrics,
session,
Expand All @@ -502,6 +522,7 @@ pub mod lenses {
let metrics = data.info.metrics.clone();
let session = data.sessions.get(&self.0).unwrap().to_owned();
let mut glyph = EditorState_ {
settings: data.shared_settings.clone(),
font: data.clone(),
metrics,
session,
Expand Down
18 changes: 12 additions & 6 deletions src/edit_session.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::cell::Ref;
use std::collections::BTreeSet;
use std::sync::Arc;

Expand All @@ -7,7 +8,7 @@ use norad::glyph::Outline;
use norad::{Glyph, GlyphName};

use crate::component::Component;
use crate::data::Workspace;
use crate::data::{Settings, SharedSettings, Workspace};
use crate::design_space::{DPoint, DVec2, ViewPort};
use crate::guides::Guide;
use crate::path::{EntityId, Path, PathPoint};
Expand Down Expand Up @@ -46,6 +47,7 @@ pub struct EditSession {
quadrant: Quadrant,
/// A string describing the current tool
pub tool_desc: Arc<str>,
pub settings: SharedSettings,
}

/// when selecting multiple points, which coordinate value do we display?
Expand Down Expand Up @@ -113,9 +115,14 @@ impl EditSession {
tool_desc: Arc::from("Select"),
quadrant: Quadrant::Center,
work_bounds,
settings: glyphs.shared_settings.clone(),
}
}

pub fn settings(&self) -> Ref<Settings> {
self.settings.borrow()
}

/// Construct a bezier of the paths in this glyph, ignoring components.
pub fn to_bezier(&self) -> BezPath {
let mut bez = BezPath::new();
Expand Down Expand Up @@ -171,19 +178,18 @@ impl EditSession {
&'a self,
point: Point,
max_dist: Option<f64>,
) -> impl Iterator<Item = EntityId> + 'a {
) -> impl Iterator<Item = (EntityId, f64)> + 'a {
let max_dist = max_dist.unwrap_or(MIN_CLICK_DISTANCE);
self.paths
.iter()
.flat_map(|p| p.points().iter())
.filter(move |p| p.screen_dist(self.viewport, point) <= max_dist)
.map(|p| p.id)
.map(move |pt| (pt.id, pt.screen_dist(self.viewport, point)))
.chain(
self.guides
.iter()
.filter(move |g| g.screen_dist(self.viewport, point) <= max_dist)
.map(|g| g.id),
.map(move |pt| (pt.id, pt.screen_dist(self.viewport, point))),
)
.filter(move |(_, dist)| *dist <= max_dist)
}

/// Return the index of the path that is currently drawing. To be currently
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ fn get_initial_state() -> AppState {
};

let mut workspace = Workspace::default();
workspace.settings_mut().show_coordinate_on_hover = true;
workspace.set_file(font_file, path);
AppState { workspace }
}
Expand Down
14 changes: 12 additions & 2 deletions src/menus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub(crate) fn make_menu(data: &AppState) -> MenuDesc<AppState> {

menu.append(file_menu(data))
.append(edit_menu())
.append(view_menu())
.append(view_menu(data))
.append(glyph_menu(data))
.append(tools_menu())
}
Expand Down Expand Up @@ -129,7 +129,7 @@ fn edit_menu<T: Data>() -> MenuDesc<T> {
)
}

fn view_menu<T: Data>() -> MenuDesc<T> {
fn view_menu(data: &AppState) -> MenuDesc<AppState> {
MenuDesc::new(LocalizedString::new("menu-view-menu").with_placeholder("View"))
.append(
MenuItem::new(
Expand All @@ -152,6 +152,16 @@ fn view_menu<T: Data>() -> MenuDesc<T> {
)
.hotkey(SysMods::Cmd, "0"),
)
.append_separator()
.append(
MenuItem::new(
LocalizedString::new("menu-item-show-coord-on-hover")
.with_placeholder("Show Coordinate On Hover"),
consts::cmd::TOGGLE_COORDINATE_HOVER,
)
.selected_if(|| data.workspace.settings().show_coordinate_on_hover),
)
.append_separator()
}

fn glyph_menu(data: &AppState) -> MenuDesc<AppState> {
Expand Down
62 changes: 56 additions & 6 deletions src/tools/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ use std::collections::BTreeSet;
use std::sync::Arc;

use druid::kurbo::{Point, Rect, Vec2};
use druid::piet::{Color, RenderContext};
use druid::piet::{
Color, FontBuilder, PietTextLayout, RenderContext, Text, TextLayout, TextLayoutBuilder,
};
use druid::{Data, Env, EventCtx, HotKey, KeyCode, KeyEvent, MouseEvent, PaintCtx, RawMods};

use crate::design_space::{DPoint, DVec2};
use crate::edit_session::EditSession;
use crate::mouse::{Drag, Mouse, MouseDelegate, TaggedEvent};
use crate::path::EntityId;
use crate::path::{EntityId, PathPoint};
use crate::tools::{EditType, Tool};

const SELECTION_RECT_BG_COLOR: Color = Color::rgba8(0xDD, 0xDD, 0xDD, 0x55);
const SELECTION_RECT_STROKE_COLOR: Color = Color::rgb8(0x53, 0x8B, 0xBB);
const HOVER_LABEL_PADDING: f64 = 8.0;

#[derive(Debug, Clone)]
enum DragState {
Expand Down Expand Up @@ -44,12 +47,56 @@ pub struct Select {
this_edit_type: Option<EditType>,
}

fn make_text_for_point(ctx: &mut PaintCtx, pt: PathPoint) -> PietTextLayout {
let text = ctx.text();
let font = text.new_font_by_name("Helvetica", 10.0).build().unwrap();
let label_text = format!("{}, {}", pt.point.x, pt.point.y);
text.new_text_layout(&font, &label_text, None)
.build()
.unwrap()
}

impl Tool for Select {
fn paint(&mut self, ctx: &mut PaintCtx, _data: &EditSession, _env: &Env) {
fn paint(&mut self, ctx: &mut PaintCtx, data: &EditSession, env: &Env) {
if let DragState::Select { rect, .. } = self.drag {
ctx.fill(rect, &SELECTION_RECT_BG_COLOR);
ctx.stroke(rect, &SELECTION_RECT_STROKE_COLOR, 1.0);
}

if data.settings().show_coordinate_on_hover {
let closest = data
.iter_items_near_point(self.last_pos, Some(8.0))
.filter(|(id, _)| !id.is_guide())
.fold((f64::MAX, None), |(nearest, its_id), (id, dist)| {
if dist < nearest {
(dist, Some(id))
} else {
(nearest, its_id)
}
})
.1
.and_then(|id| data.path_point_for_id(id));
if let Some(closest) = closest {
let text = make_text_for_point(ctx, closest);
//FIXME: be more methodical about picking a drawing location
let mut draw_pt = closest.to_screen(data.viewport);
let height = text.line_metric(0).map(|m| m.height).unwrap_or_default();
let ascent = text.line_metric(0).map(|m| m.baseline).unwrap_or_default();
draw_pt.x -= text.width() + HOVER_LABEL_PADDING;
if draw_pt.x + text.width() > ctx.size().width {
draw_pt.x -= text.width();
}
if draw_pt.y + height > ctx.size().height {
draw_pt.y -= 10.0;
}
let rect =
Rect::from_origin_size(draw_pt - Vec2::new(0., ascent), (text.width(), height))
.inset(2.0)
.to_rounded_rect(2.0);
ctx.fill(rect, &Color::WHITE.with_alpha(0.5));
ctx.draw_text(&text, draw_pt, &env.get(druid::theme::LABEL_COLOR));
}
}
}

fn key_down(
Expand Down Expand Up @@ -89,6 +136,9 @@ impl Tool for Select {
data: &mut EditSession,
_: &Env,
) -> Option<EditType> {
if data.settings().show_coordinate_on_hover {
ctx.request_paint();
}
assert!(self.this_edit_type.is_none());
let pre_rect = self.drag.drag_rect();
mouse.mouse_event(event, data, self);
Expand Down Expand Up @@ -138,7 +188,7 @@ impl MouseDelegate<EditSession> for Select {
fn left_down(&mut self, event: &MouseEvent, data: &mut EditSession) {
if event.count == 1 {
let sel = data.iter_items_near_point(event.pos, None).next();
if let Some(point_id) = sel {
if let Some((point_id, _)) = sel {
if !event.mods.shift {
// when clicking a point, if it is not selected we set it as the selection,
// otherwise we keep the selection intact for a drag.
Expand All @@ -155,7 +205,7 @@ impl MouseDelegate<EditSession> for Select {
} else if event.count == 2 {
let sel = data.iter_items_near_point(event.pos, None).next();
match sel {
Some(id)
Some((id, _))
if data
.path_point_for_id(id)
.map(|p| p.is_on_curve())
Expand All @@ -164,7 +214,7 @@ impl MouseDelegate<EditSession> for Select {
data.toggle_selected_on_curve_type();
self.this_edit_type = Some(EditType::Normal);
}
Some(id) if id.is_guide() => {
Some((id, _)) if id.is_guide() => {
data.toggle_guide(id, event.pos);
self.this_edit_type = Some(EditType::Normal);
}
Expand Down

0 comments on commit 446ba2c

Please sign in to comment.