Unverified Commit 90cff4ff authored by Jeremy Soller's avatar Jeremy Soller Committed by GitHub

Merge pull request #61 from jsalzbergedu/theme

Allow the user to specify a theme
parents 7d04798c 19776ea4
/* Every element */
* {
background: #3c4c55;
border-color: #7fc1ca;
border-radius: 0;
border-width: 1;
color: #899ba6;
}
button {
background: #4d5d66;
border-radius: 2;
}
button :active {
background: #8fd2db;
color: white;
}
button :hover {
background: #CFD6E6;
}
label {
border-width: 0;
}
menu {}
menu-button, action, separator {
border-width: 0;
}
menu-button :active, action :active {
background: #8fd2db;
}
progress {
background: #9a93e1;
border-color: #899ba6;
border-radius: 2;
}
progress-bar {
border-radius: 2;
}
selection {
background: #5294E2;
border-width: 0;
}
text-box {
background: #3c4c55;
border-radius: 2;
}
text-box :focus {
border-color: #5294E2;
}
extern crate orbtk;
use orbtk::{Action, Button, Grid, Image, Label, Menu, Point, ProgressBar, Rect, Separator, TextBox, Window, WindowBuilder};
use orbtk::theme::Theme;
use orbtk::traits::{Click, Enter, Place, Text};
fn main() {
let theme = Theme::from_path("examples/exampletheme.css").unwrap();
let mut window_builder = WindowBuilder::new(Rect::new(100, 100, 420, 730), "Orbtk - Themed");
window_builder = window_builder.theme(theme);
let mut window = window_builder.build();
let x = 10;
let mut y = 0;
let menu = Menu::new("Menu");
menu.position(x, y)
.size(32, 16);
y += menu.rect.get().height as i32 + 10;
let label = Label::new();
label.position(x, y)
.size(400, 16)
.text("Test Label");
window.add(&label);
y += label.rect.get().height as i32 + 10;
let text_box = TextBox::new();
text_box.position(x, y)
.size(332, 28)
.text_offset(6, 6)
.on_enter(move |text_box: &TextBox| {
label.text.set(text_box.text.get());
});
window.add(&text_box);
let button = Button::new();
button.position(x + text_box.rect.get().width as i32 + 8, y)
.size(48 + 12, text_box.rect.get().height)
.text("Update")
.text_offset(6, 6)
.on_click(move |_button: &Button, _point: Point| {
text_box.emit_enter();
});
window.add(&button);
y += button.rect.get().height as i32 + 10;
let progress_label = Label::new();
progress_label.text("Progress: 0%")
.position(x, y)
.size(400, 16);
window.add(&progress_label);
y += progress_label.rect.get().height as i32 + 10;
let progress_bar = ProgressBar::new();
progress_bar.position(x, y)
.size(400, 16)
.value(100)
.on_click(move |progress_bar: &ProgressBar, point: Point| {
let progress = point.x * 100 / progress_bar.rect.get().width as i32;
progress_label.text.set(format!("Progress: {}%", progress));
progress_bar.value.set(progress);
});
window.add(&progress_bar);
y += progress_bar.rect.get().height as i32 + 10;
let multi_line_label = Label::new();
multi_line_label.text("Multi-Line Text")
.position(x, y)
.size(400, 16);
window.add(&multi_line_label);
y += multi_line_label.rect.get().height as i32 + 10;
let multi_line_text_box = TextBox::new();
multi_line_text_box.position(x, y)
.size(400, 130)
.text_offset(1, 1);
window.add(&multi_line_text_box);
y += multi_line_text_box.rect.get().height as i32 + 10;
let offset_label = Label::new();
offset_label.position(x, y)
.size(400, 120)
.text("Test Offset")
.text_offset(50, 50)
.on_click(|label: &Label, _point: Point| {
label.text("Clicked");
});
window.add(&offset_label);
y += offset_label.rect.get().height as i32 + 10;
match Image::from_path("res/icon_small.png") {
Ok(image) => {
image.position(x, y);
window.add(&image);
y += image.rect.get().height as i32 + 10;
},
Err(err) => {
let label = Label::new();
label.position(x, y)
.size(400, 16)
.text(err);
window.add(&label);
y += label.rect.get().height as i32 + 10;
}
}
{
let action = Action::new("Label One");
let offset_label_clone = offset_label.clone();
action.on_click(move |_action: &Action, _point: Point| {
offset_label_clone.text.set("One".to_owned());
});
menu.add(&action);
}
{
let action = Action::new("Label Two");
let offset_label_clone = offset_label.clone();
action.on_click(move |_action: &Action, _point: Point| {
offset_label_clone.text.set("Two".to_owned());
});
menu.add(&action);
}
menu.add(&Separator::new());
{
let action = Action::new("Reset Label");
let offset_label_clone = offset_label.clone();
action.on_click(move |_action: &Action, _point: Point| {
offset_label_clone.text.set("Text Offset".to_owned());
});
menu.add(&action);
}
let grid = Grid::new();
grid.position(x, y)
.spacing(8, 8);
let label = Label::new();
label.size(32, 16).text("Grid");
grid.insert(0, 0, &label);
let label = Label::new();
label.size(32, 16).text("Test");
grid.insert(1, 0, &label);
let label = Label::new();
label.size(32, 16).text("With");
grid.insert(2, 0, &label);
let label = Label::new();
label.size(48, 16).text("Resize");
grid.insert(3, 0, &label);
let mut i = 0;
for row in 1..6 {
for col in 0..5 {
let cell = TextBox::new();
let text = format!("{}: {}, {}", i, col, row);
cell.size(text.len() as u32 * 8 + 2, 18).text(text).text_offset(1, 1);
grid.insert(col, row, &cell);
i += 1;
}
}
grid.arrange(true);
window.add(&grid);
// Add this last to put it on top
window.add(&menu);
window.exec();
}
......@@ -19,15 +19,15 @@ pub use point::Point;
pub use rect::Rect;
pub use traits::*;
pub use widgets::*;
pub use window::{InnerWindow, Window};
pub use window::{InnerWindow, Window, WindowBuilder};
pub mod cell;
pub mod dialogs;
pub mod event;
pub mod point;
pub mod rect;
pub mod theme;
pub mod traits;
pub mod widgets;
pub mod window;
pub mod draw;
pub mod theme;
......@@ -4,6 +4,11 @@ use std::collections::HashSet;
use std::sync::Arc;
use std::mem;
use std::ops::Add;
use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use std::io::Read;
static DEFAULT_THEME_CSS: &'static str = include_str!("theme.css");
......@@ -30,9 +35,20 @@ impl Theme {
}
}
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Theme, String> {
let file = try!(File::open(path).map_err(|err| format!("failed to open css: {}", err)));
let mut reader = BufReader::new(file);
let mut css = String::new();
let res = reader.read_to_string(&mut css).map_err(|err| format!("failed to read css: {}", err));
match res {
Ok(_) => Ok(Theme::parse(&css)),
Err(err) => Err(err),
}
}
fn all_rules(&self) -> Vec<Rule> {
if let Some(ref parent) = self.parent {
parent.rules.iter().chain(self.rules.iter()).cloned().collect()
self.rules.iter().chain(parent.rules.iter()).cloned().collect()
} else {
self.rules.clone()
}
......
......@@ -190,6 +190,10 @@ impl Window {
}
}
pub fn set_theme(&mut self, theme: Theme) {
self.theme = theme;
}
pub fn step(&mut self) {
self.drain_orbital_events();
self.drain_events();
......@@ -306,3 +310,72 @@ impl Window {
}
}
}
pub struct WindowBuilder<'a> {
rect: Rect,
title: &'a str,
font: Option<orbfont::Font>,
theme: Option<Theme>,
flags: Option<&'a [WindowFlag]>,
}
impl<'a> WindowBuilder<'a> {
pub fn new(rect: Rect, title: &'a str) -> Self {
WindowBuilder{rect: rect, title: title, font: None, theme: None, flags: None}
}
pub fn font(mut self, font: orbfont::Font) -> Self {
self.font = Some(font);
self
}
pub fn theme(mut self, theme: Theme) -> Self {
self.theme = Some(theme);
self
}
pub fn flags(mut self, flags: &'a [WindowFlag]) -> Self {
self.flags = Some(flags);
self
}
pub fn build(self) -> Window {
let (rect, title, font) = (self.rect, self.title, self.font);
let flags = match self.flags {
Some(flags) => flags,
None => &[],
};
let inner = InnerWindow::new_flags(
rect.x, rect.y, rect.width, rect.height,
title, flags,
).unwrap();
let theme = match self.theme {
Some(theme) => theme,
None => Theme::new(),
};
let mut events = VecDeque::new();
events.push_back(Event::Init);
Window {
inner: RefCell::new(inner),
font: font,
widgets: RefCell::new(Vec::new()),
widget_focus: Cell::new(0),
running: Cell::new(true),
theme: theme,
resize_callback: RefCell::new(None),
mouse_point: Point::new(0, 0),
mouse_left: false,
mouse_right: false,
mouse_middle: false,
events: events,
redraw: true,
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment