~saiko/game

974b80ac78e4dec13d5ab04fcd5ad03e0309da79 — 2xsaiko 1 year, 10 days ago 548f989
Text selection
2 files changed, 77 insertions(+), 3 deletions(-)

M src/ui/element/inputfield.rs
M src/ui/graphics.rs
M src/ui/element/inputfield.rs => src/ui/element/inputfield.rs +73 -3
@@ 1,5 1,5 @@
use std::borrow::Cow;
use std::cmp::max;
use std::cmp::{max, min};

use clipboard::{ClipboardContext, ClipboardProvider};
use glium::glutin::event::{ElementState, ModifiersState, ScanCode, VirtualKeyCode};


@@ 18,6 18,7 @@ pub struct InputField {
  overlay_text: String,
  text: String,
  cursor_position: usize,
  selection_start: usize,
  width: u32,
  height: u32,
  is_enabled: bool,


@@ 31,6 32,7 @@ impl InputField {
      overlay_text: String::new(),
      text: String::new(),
      cursor_position: 0,
      selection_start: 0,
      width: 0,
      height: 0,
      is_enabled: true,


@@ 102,6 104,7 @@ impl InputField {
    let i = self.search_char_left();
    self.text.replace_range(i..self.cursor_position, "");
    self.cursor_position = i;
    self.selection_start = i;
  }

  fn delete_char_right(&mut self) {


@@ 112,11 115,30 @@ impl InputField {
    let i = self.search_word_left();
    self.text.replace_range(i..self.cursor_position, "");
    self.cursor_position = i;
    self.selection_start = i;
  }

  fn delete_word_right(&mut self) {
    self.text.replace_range(self.cursor_position..self.search_word_right(), "");
  }

  fn delete_selected(&mut self) {
    let min = min(self.cursor_position, self.selection_start);
    let max = max(self.cursor_position, self.selection_start);
    self.text.replace_range(min..max, "");
    self.cursor_position = min;
    self.selection_start = min;
  }

  fn get_selected(&self) -> &str {
    let min = min(self.cursor_position, self.selection_start);
    let max = max(self.cursor_position, self.selection_start);
    &self.text[min..max]
  }

  fn has_selected(&self) -> bool {
    self.cursor_position != self.selection_start
  }
}

impl Element for InputField {


@@ 127,6 149,18 @@ impl Element for InputField {
      (true, true) => HIGHLIGHTED_COLOR,
    };

    if self.selection_start != self.cursor_position {
      g.push_matrix(|g| {
        let min = min(self.cursor_position, self.selection_start);
        let max = max(self.cursor_position, self.selection_start);
        let x = 3 + g.font_renderer().get_str_width(&self.text[..min]) as i32;
        let width = g.font_renderer().get_str_width(&self.text[min..max]) as i32;

        g.translatef(0.0, 0.0, -0.01);
        g.draw_rect(x, 3, width, g.font_renderer().get_height() as i32, Color::from_rgb8(0xfc, 0xff, 0x26));
      });
    }

    g.draw_rect(1, 1, self.width as i32 - 2, self.height as i32 - 2, color);
    g.draw_string(&self.text, 3, 3,
                  StringDrawProps::default().with_color(Color::white()));


@@ 155,15 189,25 @@ impl Element for InputField {
      match vk {
        Some(VirtualKeyCode::Back) => {
          if !modifiers.ctrl {
            self.delete_char_left();
            if self.has_selected() {
              self.delete_selected();
            } else {
              self.delete_char_left();
            }
          } else {
            self.delete_selected();
            self.delete_word_left();
          }
        }
        Some(VirtualKeyCode::Delete) => {
          if !modifiers.ctrl {
            self.delete_char_right();
            if self.has_selected() {
              self.delete_selected();
            } else {
              self.delete_char_right();
            }
          } else {
            self.delete_selected();
            self.delete_word_right();
          }
        }


@@ 173,6 217,9 @@ impl Element for InputField {
          } else {
            self.jump_word_left();
          }
          if !modifiers.shift {
            self.selection_start = self.cursor_position;
          }
        }
        Some(VirtualKeyCode::Right) => {
          if !modifiers.ctrl {


@@ 180,14 227,35 @@ impl Element for InputField {
          } else {
            self.jump_word_right();
          }
          if !modifiers.shift {
            self.selection_start = self.cursor_position;
          }
        }
        Some(VirtualKeyCode::Home) => {
          self.cursor_position = 0;
          if !modifiers.shift {
            self.selection_start = self.cursor_position;
          }
        }
        Some(VirtualKeyCode::End) => {
          self.cursor_position = self.text.len();
          if !modifiers.shift {
            self.selection_start = self.cursor_position;
          }
        }
        Some(VirtualKeyCode::A) if modifiers == m_ctrl => {
          self.cursor_position = self.text.len();
          self.selection_start = 0;
        }
        Some(VirtualKeyCode::C) if modifiers == m_ctrl => {
          if self.has_selected() {
            ClipboardProvider::new().ok().into_iter().for_each(|mut clip: ClipboardContext| {
              let _ = clip.set_contents(self.get_selected().to_owned());
            });
          }
        }
        Some(VirtualKeyCode::V) if modifiers == m_ctrl => {
          self.delete_selected();
          let inserted_text = ClipboardProvider::new().ok()
            .and_then(|mut clip: ClipboardContext| clip.get_contents().ok())
            .map_or(Cow::Borrowed(""), |s| Cow::Owned(s));


@@ 201,8 269,10 @@ impl Element for InputField {

  fn on_key_typed(&mut self, c: char) {
    if self.can_type() && !c.is_control() {
      self.delete_selected();
      self.text.insert(self.cursor_position, c);
      self.cursor_position += c.len_utf8();
      self.selection_start = self.cursor_position;
    }
  }


M src/ui/graphics.rs => src/ui/graphics.rs +4 -0
@@ 101,6 101,10 @@ impl<'a, 'b, 'c> Graphics<'a, 'b, 'c> {
    ], color);
  }

  pub fn draw_filled_rect(&mut self, x: i32, y: i32, width: i32, height: i32, color: Color) {
    todo!()
  }

  pub fn draw_texture(&mut self, x: i32, y: i32, width: i32, height: i32, dims: Option<(f32, f32, f32, f32)>, texture: &Texture2d) {
    #[derive(Copy, Clone)]
    struct Vertex {