ui: display insets (cutouts) refactoring
This commit is contained in:
parent
d3d7ca3159
commit
468783a795
7 changed files with 139 additions and 143 deletions
|
@ -73,19 +73,19 @@ public class MainActivity extends GameActivity {
|
|||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
|
||||
// Setup values to pass into native code.
|
||||
int[] cutouts = new int[]{0, 0, 0, 0};
|
||||
cutouts[0] = Utils.pxToDp(Integer.max(cutoutTop, systemBars.top), this);
|
||||
cutouts[1] = Utils.pxToDp(Integer.max(cutoutRight, systemBars.right), this);
|
||||
cutouts[2] = Utils.pxToDp(Integer.max(cutoutBottom, systemBars.bottom), this);
|
||||
cutouts[3] = Utils.pxToDp(Integer.max(cutoutLeft, systemBars.left), this);
|
||||
onDisplayCutouts(cutouts);
|
||||
int[] values = new int[]{0, 0, 0, 0};
|
||||
values[0] = Utils.pxToDp(Integer.max(cutoutTop, systemBars.top), this);
|
||||
values[1] = Utils.pxToDp(Integer.max(cutoutRight, systemBars.right), this);
|
||||
values[2] = Utils.pxToDp(Integer.max(cutoutBottom, systemBars.bottom), this);
|
||||
values[3] = Utils.pxToDp(Integer.max(cutoutLeft, systemBars.left), this);
|
||||
onDisplayInsets(values);
|
||||
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
|
||||
// Implemented into native code to handle display cutouts change.
|
||||
native void onDisplayCutouts(int[] cutouts);
|
||||
// Implemented into native code to handle display insets change.
|
||||
native void onDisplayInsets(int[] cutouts);
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
|
|
103
src/gui/app.rs
103
src/gui/app.rs
|
@ -12,10 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
use egui::Context;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
|
@ -37,9 +34,6 @@ impl<Platform> PlatformApp<Platform> {
|
|||
|
||||
impl<Platform: PlatformCallbacks> eframe::App for PlatformApp<Platform> {
|
||||
fn update(&mut self, ctx: &Context, frame: &mut eframe::Frame) {
|
||||
// Show panels to support display cutouts (insets).
|
||||
padding_panels(ctx);
|
||||
|
||||
// Show main content.
|
||||
egui::CentralPanel::default()
|
||||
.frame(egui::Frame {
|
||||
|
@ -57,102 +51,5 @@ impl<Platform: PlatformCallbacks> eframe::App for PlatformApp<Platform> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Draw panels to support display cutouts (insets).
|
||||
fn padding_panels(ctx: &Context) {
|
||||
egui::TopBottomPanel::top("top_padding_panel")
|
||||
.frame(egui::Frame {
|
||||
inner_margin: egui::style::Margin::same(0.0),
|
||||
fill: Colors::YELLOW,
|
||||
..Default::default()
|
||||
})
|
||||
.show_separator_line(false)
|
||||
.resizable(false)
|
||||
.exact_height(get_top_display_cutout())
|
||||
.show(ctx, |_ui| {});
|
||||
|
||||
egui::TopBottomPanel::bottom("bottom_padding_panel")
|
||||
.frame(egui::Frame {
|
||||
inner_margin: egui::style::Margin::same(0.0),
|
||||
fill: Colors::BLACK,
|
||||
..Default::default()
|
||||
})
|
||||
.show_separator_line(false)
|
||||
.resizable(false)
|
||||
.exact_height(get_bottom_display_cutout())
|
||||
.show(ctx, |_ui| {});
|
||||
|
||||
egui::SidePanel::right("right_padding_panel")
|
||||
.frame(egui::Frame {
|
||||
inner_margin: egui::style::Margin::same(0.0),
|
||||
fill: Colors::YELLOW,
|
||||
..Default::default()
|
||||
})
|
||||
.show_separator_line(false)
|
||||
.resizable(false)
|
||||
.max_width(get_right_display_cutout())
|
||||
.show(ctx, |_ui| {});
|
||||
|
||||
egui::SidePanel::left("left_padding_panel")
|
||||
.frame(egui::Frame {
|
||||
inner_margin: egui::style::Margin::same(0.0),
|
||||
fill: Colors::YELLOW,
|
||||
..Default::default()
|
||||
})
|
||||
.show_separator_line(false)
|
||||
.resizable(false)
|
||||
.max_width(get_left_display_cutout())
|
||||
.show(ctx, |_ui| {});
|
||||
}
|
||||
|
||||
/// Get top display cutout (inset) size.
|
||||
pub fn get_top_display_cutout() -> f32 {
|
||||
TOP_DISPLAY_CUTOUT.load(Ordering::Relaxed) as f32
|
||||
}
|
||||
|
||||
/// Get right display cutout (inset) size.
|
||||
pub fn get_right_display_cutout() -> f32 {
|
||||
RIGHT_DISPLAY_CUTOUT.load(Ordering::Relaxed) as f32
|
||||
}
|
||||
|
||||
/// Get bottom display cutout (inset) size.
|
||||
pub fn get_bottom_display_cutout() -> f32 {
|
||||
BOTTOM_DISPLAY_CUTOUT.load(Ordering::Relaxed) as f32
|
||||
}
|
||||
|
||||
/// Get left display cutout (inset) size.
|
||||
pub fn get_left_display_cutout() -> f32 {
|
||||
LEFT_DISPLAY_CUTOUT.load(Ordering::Relaxed) as f32
|
||||
}
|
||||
|
||||
/// Fields to handle platform-specific display cutouts (insets).
|
||||
lazy_static! {
|
||||
static ref TOP_DISPLAY_CUTOUT: AtomicI32 = AtomicI32::new(0);
|
||||
static ref RIGHT_DISPLAY_CUTOUT: AtomicI32 = AtomicI32::new(0);
|
||||
static ref BOTTOM_DISPLAY_CUTOUT: AtomicI32 = AtomicI32::new(0);
|
||||
static ref LEFT_DISPLAY_CUTOUT: AtomicI32 = AtomicI32::new(0);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
/// Callback from Java code to update display cutouts (insets).
|
||||
pub extern "C" fn Java_mw_gri_android_MainActivity_onDisplayCutouts(
|
||||
_env: jni::JNIEnv,
|
||||
_class: jni::objects::JObject,
|
||||
cutouts: jni::sys::jarray
|
||||
) {
|
||||
use jni::objects::{JObject, JPrimitiveArray};
|
||||
|
||||
let mut array: [i32; 4] = [0; 4];
|
||||
unsafe {
|
||||
let j_obj = JObject::from_raw(cutouts);
|
||||
let j_arr = JPrimitiveArray::from(j_obj);
|
||||
_env.get_int_array_region(j_arr, 0, array.as_mut()).unwrap();
|
||||
}
|
||||
TOP_DISPLAY_CUTOUT.store(array[0], Ordering::Relaxed);
|
||||
RIGHT_DISPLAY_CUTOUT.store(array[1], Ordering::Relaxed);
|
||||
BOTTOM_DISPLAY_CUTOUT.store(array[2], Ordering::Relaxed);
|
||||
LEFT_DISPLAY_CUTOUT.store(array[3], Ordering::Relaxed);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ impl Accounts {
|
|||
None
|
||||
}, TitleAction::new(PLUS, || {
|
||||
//TODO: add account
|
||||
}), ui);
|
||||
}), ui, frame);
|
||||
|
||||
egui::CentralPanel::default()
|
||||
.frame(egui::Frame {
|
||||
|
|
|
@ -12,16 +12,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::{Color32, lerp, Rgba, RichText};
|
||||
use egui::RichText;
|
||||
use egui::style::Margin;
|
||||
use egui_extras::{Size, StripBuilder};
|
||||
use grin_chain::SyncStatus;
|
||||
|
||||
use crate::AppConfig;
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, POWER};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, ModalContainer, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings, Root, TitleAction, TitleType, TitlePanel, View};
|
||||
use crate::gui::views::{Modal, ModalContainer, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings, Root, TitleAction, TitlePanel, TitleType, View};
|
||||
use crate::gui::views::network::setup::{DandelionSetup, NodeSetup, P2PSetup, PoolSetup, StratumSetup};
|
||||
use crate::node::Node;
|
||||
|
||||
|
@ -122,7 +120,7 @@ impl Network {
|
|||
egui::TopBottomPanel::bottom("network_tabs")
|
||||
.frame(egui::Frame {
|
||||
fill: Colors::FILL,
|
||||
inner_margin: Margin::same(4.0),
|
||||
inner_margin: Self::tabs_inner_margin(ui, frame),
|
||||
..Default::default()
|
||||
})
|
||||
.show_inside(ui, |ui| {
|
||||
|
@ -132,12 +130,7 @@ impl Network {
|
|||
egui::CentralPanel::default()
|
||||
.frame(egui::Frame {
|
||||
stroke: View::DEFAULT_STROKE,
|
||||
inner_margin: Margin {
|
||||
left: 4.0,
|
||||
right: 4.0,
|
||||
top: 3.0,
|
||||
bottom: 4.0,
|
||||
},
|
||||
inner_margin: Self::content_inner_margin(ui, frame),
|
||||
fill: Colors::WHITE,
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -151,6 +144,26 @@ impl Network {
|
|||
}
|
||||
}
|
||||
|
||||
/// Calculate tabs inner margin based on display insets (cutouts).
|
||||
fn tabs_inner_margin(ui: &mut egui::Ui, frame: &mut eframe::Frame) -> Margin {
|
||||
Margin {
|
||||
left: View::far_left_inset_margin(ui) + 4.0,
|
||||
right: View::far_right_inset_margin(ui, frame) + 4.0,
|
||||
top: 4.0,
|
||||
bottom: View::get_bottom_inset() + 4.0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate content inner margin based on display insets (cutouts).
|
||||
fn content_inner_margin(ui: &mut egui::Ui, frame: &mut eframe::Frame) -> Margin {
|
||||
Margin {
|
||||
left: View::far_left_inset_margin(ui) + 4.0,
|
||||
right: View::far_right_inset_margin(ui, frame) + 4.0,
|
||||
top: 3.0,
|
||||
bottom: 4.0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw tab buttons in the bottom of the screen.
|
||||
fn tabs_ui(&mut self, ui: &mut egui::Ui) {
|
||||
ui.scope(|ui| {
|
||||
|
@ -202,7 +215,7 @@ impl Network {
|
|||
})
|
||||
} else {
|
||||
None
|
||||
}, ui);
|
||||
}, ui, frame);
|
||||
}
|
||||
|
||||
/// Content to draw when node is disabled.
|
||||
|
|
|
@ -11,14 +11,11 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::cmp::min;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use egui::os::OperatingSystem;
|
||||
use egui::RichText;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use crate::gui::app::{get_left_display_cutout, get_right_display_cutout};
|
||||
use crate::gui::Colors;
|
||||
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
|
@ -75,7 +72,7 @@ impl Root {
|
|||
pub const EXIT_MODAL_ID: &'static str = "exit_confirmation";
|
||||
|
||||
/// Default width of side panel at application UI.
|
||||
pub const SIDE_PANEL_MIN_WIDTH: i64 = 400;
|
||||
pub const SIDE_PANEL_MIN_WIDTH: f32 = 400.0;
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
||||
// Show opened exit confirmation Modal content.
|
||||
|
@ -83,20 +80,20 @@ impl Root {
|
|||
self.exit_modal_content(ui, frame, cb);
|
||||
}
|
||||
|
||||
// Show network content on side panel.
|
||||
let (is_panel_open, panel_width) = Self::side_panel_state_width(frame);
|
||||
egui::SidePanel::left("network_panel")
|
||||
.resizable(false)
|
||||
.exact_width(panel_width)
|
||||
.frame(egui::Frame::none())
|
||||
.show_animated_inside(ui, is_panel_open, |ui| {
|
||||
// Show network content on side panel.
|
||||
self.side_panel.ui(ui, frame, cb);
|
||||
});
|
||||
|
||||
// Show accounts content on central panel.
|
||||
egui::CentralPanel::default()
|
||||
.frame(egui::Frame::none())
|
||||
.show_inside(ui, |ui| {
|
||||
// Show accounts content on central panel.
|
||||
self.central_content.ui(ui, frame, cb);
|
||||
});
|
||||
}
|
||||
|
@ -105,12 +102,10 @@ impl Root {
|
|||
fn side_panel_state_width(frame: &mut eframe::Frame) -> (bool, f32) {
|
||||
let dual_panel_mode = Self::is_dual_panel_mode(frame);
|
||||
let is_panel_open = dual_panel_mode || Self::is_side_panel_open();
|
||||
let side_cutouts = get_left_display_cutout() + get_right_display_cutout();
|
||||
let panel_width = if dual_panel_mode {
|
||||
let available_width = (frame.info().window_info.size.x - side_cutouts) as i64;
|
||||
min(available_width, Self::SIDE_PANEL_MIN_WIDTH) as f32
|
||||
Self::SIDE_PANEL_MIN_WIDTH + View::get_left_inset()
|
||||
} else {
|
||||
frame.info().window_info.size.x - side_cutouts
|
||||
frame.info().window_info.size.x
|
||||
};
|
||||
(is_panel_open, panel_width)
|
||||
}
|
||||
|
@ -122,9 +117,9 @@ impl Root {
|
|||
// Screen is wide if width is greater than height or just 20% smaller.
|
||||
let is_wide_screen = w > h || w + (w * 0.2) >= h;
|
||||
// Dual panel mode is available when window is wide and its width is at least 2 times
|
||||
// greater than minimal width of the side panel plus display cutouts from both sides.
|
||||
let side_cutouts = get_left_display_cutout() + get_right_display_cutout();
|
||||
is_wide_screen && w >= (Self::SIDE_PANEL_MIN_WIDTH as f32 * 2.0) + side_cutouts
|
||||
// greater than minimal width of the side panel plus display insets from both sides.
|
||||
let side_insets = View::get_left_inset() + View::get_right_inset();
|
||||
is_wide_screen && w >= (Self::SIDE_PANEL_MIN_WIDTH * 2.0) + side_insets
|
||||
}
|
||||
|
||||
/// Toggle [`Network`] panel state.
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::{Color32, Id, lerp, Rgba, RichText};
|
||||
use egui::{Color32, Id, lerp, Rgba};
|
||||
use egui::style::Margin;
|
||||
use egui_extras::{Size, StripBuilder};
|
||||
|
||||
|
@ -43,7 +43,12 @@ pub struct TitlePanel;
|
|||
impl TitlePanel {
|
||||
pub const DEFAULT_HEIGHT: f32 = 54.0;
|
||||
|
||||
pub fn ui(title: TitleType, l: Option<TitleAction>, r: Option<TitleAction>, ui: &mut egui::Ui) {
|
||||
pub fn ui(title: TitleType,
|
||||
left_action: Option<TitleAction>,
|
||||
right_action: Option<TitleAction>,
|
||||
ui: &mut egui::Ui,
|
||||
frame: &mut eframe::Frame) {
|
||||
// Setup identifier.
|
||||
let id = match &title {
|
||||
TitleType::Single(text) => Id::from(text.clone()),
|
||||
TitleType::WithSubTitle(text, _, _) => Id::from(text.clone())
|
||||
|
@ -52,7 +57,7 @@ impl TitlePanel {
|
|||
.resizable(false)
|
||||
.exact_height(Self::DEFAULT_HEIGHT)
|
||||
.frame(egui::Frame {
|
||||
outer_margin: Margin::same(-1.0),
|
||||
inner_margin: Self::inner_margin(ui, frame),
|
||||
fill: Colors::YELLOW,
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -63,7 +68,7 @@ impl TitlePanel {
|
|||
.size(Size::exact(Self::DEFAULT_HEIGHT))
|
||||
.horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
Self::draw_action(ui, l);
|
||||
Self::action_ui(ui, left_action);
|
||||
});
|
||||
match title {
|
||||
TitleType::Single(text) => {
|
||||
|
@ -81,14 +86,24 @@ impl TitlePanel {
|
|||
}
|
||||
}
|
||||
strip.cell(|ui| {
|
||||
Self::draw_action(ui, r);
|
||||
Self::action_ui(ui, right_action);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Calculate inner margin based on display insets (cutouts).
|
||||
fn inner_margin(ui: &mut egui::Ui, frame: &mut eframe::Frame) -> Margin {
|
||||
Margin {
|
||||
left: View::far_left_inset_margin(ui),
|
||||
right: View::far_right_inset_margin(ui, frame),
|
||||
top: View::get_top_inset(),
|
||||
bottom: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw panel [`TitleAction`].
|
||||
fn draw_action(ui: &mut egui::Ui, action: Option<TitleAction>) {
|
||||
fn action_ui(ui: &mut egui::Ui, action: Option<TitleAction>) {
|
||||
if action.is_some() {
|
||||
let action = action.unwrap();
|
||||
ui.centered_and_justified(|ui| {
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
use egui::{Button, PointerState, Response, RichText, Sense, Spinner, Widget};
|
||||
use egui::epaint::{Color32, FontId, RectShape, Rounding, Stroke};
|
||||
use egui::epaint::text::TextWrapping;
|
||||
use egui::text::{LayoutJob, TextFormat};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{CHECK_SQUARE, SQUARE};
|
||||
|
@ -26,6 +29,26 @@ impl View {
|
|||
/// Default stroke around views.
|
||||
pub const DEFAULT_STROKE: Stroke = Stroke { width: 1.0, color: Colors::STROKE };
|
||||
|
||||
/// Calculate margin for far left view based on display insets (cutouts).
|
||||
pub fn far_left_inset_margin(ui: &mut egui::Ui) -> f32 {
|
||||
if ui.available_rect_before_wrap().min.x == 0.0 {
|
||||
Self::get_left_inset()
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate margin for far left view based on display insets (cutouts).
|
||||
pub fn far_right_inset_margin(ui: &mut egui::Ui, frame: &mut eframe::Frame) -> f32 {
|
||||
let container_width = ui.available_rect_before_wrap().max.x as i32;
|
||||
let display_width = frame.info().window_info.size.x as i32;
|
||||
if container_width == display_width {
|
||||
Self::get_right_inset()
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Cut long text with ﹍ character.
|
||||
fn ellipsize(text: String, size: f32, color: Color32) -> LayoutJob {
|
||||
let mut job = LayoutJob::single_section(text, TextFormat {
|
||||
|
@ -238,4 +261,57 @@ impl View {
|
|||
painter.round_to_pixel(line_rect.center().y),
|
||||
Stroke { width: 1.0, color });
|
||||
}
|
||||
|
||||
/// Get top display inset (cutout) size.
|
||||
pub fn get_top_inset() -> f32 {
|
||||
TOP_DISPLAY_INSET.load(Ordering::Relaxed) as f32
|
||||
}
|
||||
|
||||
/// Get right display inset (cutout) size.
|
||||
pub fn get_right_inset() -> f32 {
|
||||
RIGHT_DISPLAY_INSET.load(Ordering::Relaxed) as f32
|
||||
}
|
||||
|
||||
/// Get bottom display inset (cutout) size.
|
||||
pub fn get_bottom_inset() -> f32 {
|
||||
BOTTOM_DISPLAY_INSET.load(Ordering::Relaxed) as f32
|
||||
}
|
||||
|
||||
/// Get left display inset (cutout) size.
|
||||
pub fn get_left_inset() -> f32 {
|
||||
LEFT_DISPLAY_INSET.load(Ordering::Relaxed) as f32
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Fields to handle platform-specific display insets (cutouts).
|
||||
lazy_static! {
|
||||
static ref TOP_DISPLAY_INSET: AtomicI32 = AtomicI32::new(0);
|
||||
static ref RIGHT_DISPLAY_INSET: AtomicI32 = AtomicI32::new(0);
|
||||
static ref BOTTOM_DISPLAY_INSET: AtomicI32 = AtomicI32::new(0);
|
||||
static ref LEFT_DISPLAY_INSET: AtomicI32 = AtomicI32::new(0);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
/// Callback from Java code to update display insets (cutouts).
|
||||
pub extern "C" fn Java_mw_gri_android_MainActivity_onDisplayInsets(
|
||||
_env: jni::JNIEnv,
|
||||
_class: jni::objects::JObject,
|
||||
cutouts: jni::sys::jarray
|
||||
) {
|
||||
use jni::objects::{JObject, JPrimitiveArray};
|
||||
|
||||
let mut array: [i32; 4] = [0; 4];
|
||||
unsafe {
|
||||
let j_obj = JObject::from_raw(cutouts);
|
||||
let j_arr = JPrimitiveArray::from(j_obj);
|
||||
_env.get_int_array_region(j_arr, 0, array.as_mut()).unwrap();
|
||||
}
|
||||
TOP_DISPLAY_INSET.store(array[0], Ordering::Relaxed);
|
||||
RIGHT_DISPLAY_INSET.store(array[1], Ordering::Relaxed);
|
||||
BOTTOM_DISPLAY_INSET.store(array[2], Ordering::Relaxed);
|
||||
LEFT_DISPLAY_INSET.store(array[3], Ordering::Relaxed);
|
||||
}
|
Loading…
Reference in a new issue