mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-27 15:03:20 +03:00
Popup error messages when the user tries to do something invalid (like filtering a one-way street)
This commit is contained in:
parent
f0b09633c2
commit
86f908946f
@ -51,6 +51,7 @@ impl FreehandFilters {
|
||||
continue;
|
||||
}
|
||||
let road = app.map.get_r(*r);
|
||||
// Don't show error messages for these
|
||||
if !PathConstraints::Car.can_use_road(road, &app.map)
|
||||
|| road.oneway_for_driving().is_some()
|
||||
{
|
||||
|
@ -9,7 +9,7 @@ use widgetry::{
|
||||
};
|
||||
|
||||
use crate::draw_cells::RenderCells;
|
||||
use crate::edit::{EditNeighbourhood, Tab};
|
||||
use crate::edit::{EditNeighbourhood, EditOutcome, Tab};
|
||||
use crate::filters::auto::Heuristic;
|
||||
use crate::shortcuts::find_shortcuts;
|
||||
use crate::{colors, App, Neighbourhood, NeighbourhoodID, Transition};
|
||||
@ -179,9 +179,15 @@ impl State<App> for Viewer {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if self.edit.event(ctx, app) {
|
||||
self.neighbourhood = Neighbourhood::new(ctx, app, self.neighbourhood.id);
|
||||
self.update(ctx, app);
|
||||
match self.edit.event(ctx, app) {
|
||||
EditOutcome::Nothing => {}
|
||||
EditOutcome::Recalculate => {
|
||||
self.neighbourhood = Neighbourhood::new(ctx, app, self.neighbourhood.id);
|
||||
self.update(ctx, app);
|
||||
}
|
||||
EditOutcome::Transition(t) => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
Transition::Keep
|
||||
|
@ -4,7 +4,7 @@ use widgetry::mapspace::{World, WorldOutcome};
|
||||
use widgetry::tools::open_browser;
|
||||
use widgetry::{lctrl, EventCtx, Image, Key, Line, Text, TextExt, Widget};
|
||||
|
||||
use super::Obj;
|
||||
use super::{EditOutcome, Obj};
|
||||
use crate::shortcuts::Shortcuts;
|
||||
use crate::{after_edit, colors, App, DiagonalFilter, Neighbourhood};
|
||||
|
||||
@ -86,16 +86,23 @@ pub fn make_world(
|
||||
world
|
||||
}
|
||||
|
||||
pub fn handle_world_outcome(ctx: &mut EventCtx, app: &mut App, outcome: WorldOutcome<Obj>) -> bool {
|
||||
pub fn handle_world_outcome(
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
outcome: WorldOutcome<Obj>,
|
||||
) -> EditOutcome {
|
||||
let map = &app.map;
|
||||
match outcome {
|
||||
WorldOutcome::ClickedObject(Obj::InteriorRoad(r)) => {
|
||||
let road = map.get_r(r);
|
||||
// Filtering a road that's already marked bike-only doesn't make sense. Likewise for
|
||||
// one-ways.
|
||||
if !PathConstraints::Car.can_use_road(road, map) || road.oneway_for_driving().is_some()
|
||||
{
|
||||
return true;
|
||||
if !PathConstraints::Car.can_use_road(road, map) {
|
||||
return EditOutcome::error(
|
||||
ctx,
|
||||
"This street isn't accessible by car; no need for a filter",
|
||||
);
|
||||
}
|
||||
if road.oneway_for_driving().is_some() {
|
||||
return EditOutcome::error(ctx, "You can't filter a one-way street");
|
||||
}
|
||||
|
||||
app.session.modal_filters.before_edit();
|
||||
@ -111,22 +118,22 @@ pub fn handle_world_outcome(ctx: &mut EventCtx, app: &mut App, outcome: WorldOut
|
||||
app.session.modal_filters.roads.insert(r, distance);
|
||||
}
|
||||
after_edit(ctx, app);
|
||||
true
|
||||
EditOutcome::Recalculate
|
||||
}
|
||||
WorldOutcome::ClickedObject(Obj::InteriorIntersection(i)) => {
|
||||
app.session.modal_filters.before_edit();
|
||||
DiagonalFilter::cycle_through_alternatives(app, i);
|
||||
after_edit(ctx, app);
|
||||
true
|
||||
EditOutcome::Recalculate
|
||||
}
|
||||
WorldOutcome::Keypress("debug", Obj::InteriorIntersection(i)) => {
|
||||
open_browser(app.map.get_i(i).orig_id.to_string());
|
||||
false
|
||||
EditOutcome::Nothing
|
||||
}
|
||||
WorldOutcome::Keypress("debug", Obj::InteriorRoad(r)) => {
|
||||
open_browser(app.map.get_r(r).orig_id.osm_way_id.to_string());
|
||||
false
|
||||
EditOutcome::Nothing
|
||||
}
|
||||
_ => false,
|
||||
_ => EditOutcome::Nothing,
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ mod one_ways;
|
||||
|
||||
use map_model::{IntersectionID, RoadID};
|
||||
use widgetry::mapspace::{ObjectID, World};
|
||||
use widgetry::tools::PopupMsg;
|
||||
use widgetry::{EventCtx, Key, Line, Panel, PanelBuilder, Widget, DEFAULT_CORNER_RADIUS};
|
||||
|
||||
use crate::shortcuts::Shortcuts;
|
||||
@ -72,6 +73,23 @@ pub enum Obj {
|
||||
}
|
||||
impl ObjectID for Obj {}
|
||||
|
||||
pub enum EditOutcome {
|
||||
Nothing,
|
||||
/// The neighbourhood has changed and the caller should recalculate stuff, including the panel
|
||||
Recalculate,
|
||||
Transition(Transition),
|
||||
}
|
||||
|
||||
impl EditOutcome {
|
||||
fn error(ctx: &mut EventCtx, msg: &str) -> Self {
|
||||
Self::Transition(Transition::Push(PopupMsg::new_state(
|
||||
ctx,
|
||||
"Error",
|
||||
vec![msg],
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl EditNeighbourhood {
|
||||
pub fn temporary() -> Self {
|
||||
Self {
|
||||
@ -122,15 +140,17 @@ impl EditNeighbourhood {
|
||||
crate::components::LeftPanel::builder(ctx, top_panel, contents)
|
||||
}
|
||||
|
||||
/// If true, the neighbourhood has changed and the caller should recalculate stuff, including
|
||||
/// the panel
|
||||
pub fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> bool {
|
||||
pub fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> EditOutcome {
|
||||
let outcome = self.world.event(ctx);
|
||||
if app.session.edit_filters {
|
||||
let outcome = if app.session.edit_filters {
|
||||
filters::handle_world_outcome(ctx, app, outcome)
|
||||
} else {
|
||||
one_ways::handle_world_outcome(ctx, app, outcome)
|
||||
};
|
||||
if matches!(outcome, EditOutcome::Transition(_)) {
|
||||
self.world.hack_unset_hovering();
|
||||
}
|
||||
outcome
|
||||
}
|
||||
|
||||
pub fn handle_panel_action(
|
||||
|
@ -4,7 +4,7 @@ use raw_map::{Direction, DrivingSide, LaneSpec, LaneType};
|
||||
use widgetry::mapspace::{World, WorldOutcome};
|
||||
use widgetry::{EventCtx, Image, Text, TextExt, Widget};
|
||||
|
||||
use super::Obj;
|
||||
use super::{EditOutcome, Obj};
|
||||
use crate::{colors, App, Neighbourhood};
|
||||
|
||||
pub fn widget(ctx: &mut EventCtx) -> Widget {
|
||||
@ -45,7 +45,11 @@ pub fn make_world(ctx: &mut EventCtx, app: &App, neighbourhood: &Neighbourhood)
|
||||
world
|
||||
}
|
||||
|
||||
pub fn handle_world_outcome(ctx: &mut EventCtx, app: &mut App, outcome: WorldOutcome<Obj>) -> bool {
|
||||
pub fn handle_world_outcome(
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
outcome: WorldOutcome<Obj>,
|
||||
) -> EditOutcome {
|
||||
match outcome {
|
||||
WorldOutcome::ClickedObject(Obj::InteriorRoad(r)) => {
|
||||
let leftmost_dir = if app.map.get_config().driving_side == DrivingSide::Right {
|
||||
@ -113,8 +117,8 @@ pub fn handle_world_outcome(ctx: &mut EventCtx, app: &mut App, outcome: WorldOut
|
||||
app.map.keep_pathfinder_despite_edits();
|
||||
});
|
||||
|
||||
true
|
||||
EditOutcome::Recalculate
|
||||
}
|
||||
_ => false,
|
||||
_ => EditOutcome::Nothing,
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use map_model::{PathRequest, NORMAL_LANE_THICKNESS};
|
||||
use widgetry::mapspace::ToggleZoomed;
|
||||
use widgetry::{EventCtx, GfxCtx, Key, Line, Outcome, Panel, State, Text, TextExt, Widget};
|
||||
|
||||
use crate::edit::{EditNeighbourhood, Tab};
|
||||
use crate::edit::{EditNeighbourhood, EditOutcome, Tab};
|
||||
use crate::shortcuts::{find_shortcuts, Shortcuts};
|
||||
use crate::{colors, App, Neighbourhood, NeighbourhoodID, Transition};
|
||||
|
||||
@ -209,15 +209,21 @@ impl State<App> for BrowseShortcuts {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if self.edit.event(ctx, app) {
|
||||
// Reset state, but if possible, preserve the current individual shortcut.
|
||||
let current_request = self.shortcuts.paths[self.current_idx].get_req().clone();
|
||||
return Transition::Replace(BrowseShortcuts::new_state(
|
||||
ctx,
|
||||
app,
|
||||
self.neighbourhood.id,
|
||||
Some(current_request),
|
||||
));
|
||||
match self.edit.event(ctx, app) {
|
||||
EditOutcome::Nothing => {}
|
||||
EditOutcome::Recalculate => {
|
||||
// Reset state, but if possible, preserve the current individual shortcut.
|
||||
let current_request = self.shortcuts.paths[self.current_idx].get_req().clone();
|
||||
return Transition::Replace(BrowseShortcuts::new_state(
|
||||
ctx,
|
||||
app,
|
||||
self.neighbourhood.id,
|
||||
Some(current_request),
|
||||
));
|
||||
}
|
||||
EditOutcome::Transition(t) => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
Transition::Keep
|
||||
|
Loading…
Reference in New Issue
Block a user