multiple_displays/
multiple-displays.rs1extern crate embedded_graphics;
6extern crate embedded_graphics_simulator;
7
8use embedded_graphics::{
9 geometry::AnchorPoint,
10 mono_font::{ascii::FONT_10X20, MonoTextStyle},
11 pixelcolor::{BinaryColor, Rgb565, Rgb888},
12 prelude::*,
13 primitives::{Circle, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle, StrokeAlignment},
14 text::{Alignment, Baseline, Text, TextStyle, TextStyleBuilder},
15};
16use embedded_graphics_simulator::{
17 sdl2::MouseButton, BinaryColorTheme, MultiWindow, OutputSettings, OutputSettingsBuilder,
18 SimulatorDisplay, SimulatorEvent,
19};
20
21const OLED_TEXT: MonoTextStyle<BinaryColor> = MonoTextStyle::new(&FONT_10X20, BinaryColor::On);
22const TFT_TEXT: MonoTextStyle<Rgb565> =
23 MonoTextStyle::new(&FONT_10X20, Rgb565::CSS_LIGHT_SLATE_GRAY);
24const CENTERED: TextStyle = TextStyleBuilder::new()
25 .alignment(Alignment::Center)
26 .baseline(Baseline::Middle)
27 .build();
28
29fn display_offset(window_size: Size, display_size: Size, anchor_point: AnchorPoint) -> Point {
31 let layout_rect = Rectangle::new(Point::zero(), window_size).offset(-20);
33
34 layout_rect.resized(display_size, anchor_point).top_left
37}
38
39fn main() -> Result<(), core::convert::Infallible> {
40 let mut oled_displays = Vec::new();
43 for i in 0..3 {
44 let mut oled: SimulatorDisplay<BinaryColor> = SimulatorDisplay::new(Size::new(128, 64));
45
46 Text::with_text_style(
47 &format!("Display {i}"),
48 oled.bounding_box().center(),
49 OLED_TEXT,
50 CENTERED,
51 )
52 .draw(&mut oled)
53 .unwrap();
54
55 oled_displays.push(oled);
56 }
57
58 let mut tft: SimulatorDisplay<Rgb565> = SimulatorDisplay::new(Size::new(320, 240));
61 tft.clear(Rgb565::new(5, 10, 5)).unwrap();
62
63 Text::with_text_style(
64 &format!("Draw here"),
65 tft.bounding_box().center(),
66 TFT_TEXT,
67 CENTERED,
68 )
69 .draw(&mut tft)
70 .unwrap();
71
72 let window_size = Size::new(1300, 500);
75 let mut window = MultiWindow::new("Multiple displays example", window_size);
76 window.clear(Rgb888::CSS_DIM_GRAY);
77
78 let oled_settings = OutputSettingsBuilder::new()
79 .theme(BinaryColorTheme::OledBlue)
80 .scale(2)
81 .build();
82 let oled_size = oled_displays[0].output_size(&oled_settings);
83
84 for (oled, anchor) in oled_displays.iter().zip(
85 [
86 AnchorPoint::TopLeft,
87 AnchorPoint::TopCenter,
88 AnchorPoint::TopRight,
89 ]
90 .into_iter(),
91 ) {
92 let offset = display_offset(window_size, oled_size, anchor);
93 window.add_display(&oled, offset, &oled_settings);
94 }
95
96 let tft_settings = OutputSettings::default();
97 let tft_size = tft.output_size(&tft_settings);
98 let tft_offset = display_offset(window_size, tft_size, AnchorPoint::BottomCenter);
99
100 window.add_display(&tft, tft_offset, &tft_settings);
101
102 let border_style = PrimitiveStyleBuilder::new()
103 .stroke_width(5)
104 .stroke_alignment(StrokeAlignment::Inside)
105 .build();
106
107 let mut mouse_down = false;
108
109 'running: loop {
110 for oled in &oled_displays {
113 window.update_display(oled);
114 }
115 window.update_display(&tft);
116 window.flush();
117
118 for event in window.events() {
119 match event {
120 SimulatorEvent::MouseMove { point } => {
121 for oled in &mut oled_displays {
126 let is_inside = window.translate_mouse_position(oled, point).is_some();
127
128 let style = PrimitiveStyleBuilder::from(&border_style)
129 .stroke_color(BinaryColor::from(is_inside))
130 .build();
131
132 oled.bounding_box().into_styled(style).draw(oled).unwrap();
133 }
134
135 if mouse_down {
136 if let Some(point) = window.translate_mouse_position(&tft, point) {
137 Circle::with_center(point, 10)
138 .into_styled(PrimitiveStyle::with_fill(Rgb565::CSS_DODGER_BLUE))
139 .draw(&mut tft)
140 .unwrap();
141 }
142 }
143 }
144 SimulatorEvent::MouseButtonDown {
145 mouse_btn: MouseButton::Left,
146 ..
147 } => {
148 mouse_down = true;
149 }
150 SimulatorEvent::MouseButtonUp {
151 mouse_btn: MouseButton::Left,
152 ..
153 } => {
154 mouse_down = false;
155 }
156 SimulatorEvent::Quit => break 'running,
157 _ => {}
158 }
159 }
160 }
161
162 Ok(())
163}