summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/Cargo.toml10
-rw-r--r--core/src/element.rs18
-rw-r--r--core/src/keyboard.rs7
-rw-r--r--core/src/keyboard/event.rs29
-rw-r--r--core/src/keyboard/key.rs744
-rw-r--r--core/src/keyboard/key_code.rs203
-rw-r--r--core/src/keyboard/location.rs12
-rw-r--r--core/src/layout.rs106
-rw-r--r--core/src/layout/flex.rs117
-rw-r--r--core/src/layout/limits.rs88
-rw-r--r--core/src/layout/node.rs35
-rw-r--r--core/src/length.rs18
-rw-r--r--core/src/lib.rs2
-rw-r--r--core/src/mouse/button.rs6
-rw-r--r--core/src/padding.rs6
-rw-r--r--core/src/point.rs20
-rw-r--r--core/src/size.rs24
-rw-r--r--core/src/time.rs13
-rw-r--r--core/src/widget.rs15
-rw-r--r--core/src/widget/text.rs58
-rw-r--r--core/src/window/event.rs2
21 files changed, 1144 insertions, 389 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 4672c754..be92a572 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -13,18 +13,18 @@ keywords.workspace = true
[dependencies]
bitflags.workspace = true
log.workspace = true
+num-traits.workspace = true
+smol_str.workspace = true
thiserror.workspace = true
+web-time.workspace = true
xxhash-rust.workspace = true
-num-traits.workspace = true
palette.workspace = true
palette.optional = true
-[target.'cfg(target_arch = "wasm32")'.dependencies]
-instant.workspace = true
-
[target.'cfg(windows)'.dependencies]
-raw-window-handle.workspace = true
+# TODO: Use `workspace` dependency once `wgpu` upgrades `raw-window-handle`
+raw-window-handle = "0.6"
[dev-dependencies]
approx = "0.5"
diff --git a/core/src/element.rs b/core/src/element.rs
index dea111af..8b510218 100644
--- a/core/src/element.rs
+++ b/core/src/element.rs
@@ -6,7 +6,7 @@ use crate::renderer;
use crate::widget;
use crate::widget::tree::{self, Tree};
use crate::{
- Clipboard, Color, Layout, Length, Rectangle, Shell, Vector, Widget,
+ Clipboard, Color, Layout, Length, Rectangle, Shell, Size, Vector, Widget,
};
use std::any::Any;
@@ -296,12 +296,8 @@ where
self.widget.diff(tree);
}
- fn width(&self) -> Length {
- self.widget.width()
- }
-
- fn height(&self) -> Length {
- self.widget.height()
+ fn size(&self) -> Size<Length> {
+ self.widget.size()
}
fn layout(
@@ -466,12 +462,8 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
where
Renderer: crate::Renderer,
{
- fn width(&self) -> Length {
- self.element.widget.width()
- }
-
- fn height(&self) -> Length {
- self.element.widget.height()
+ fn size(&self) -> Size<Length> {
+ self.element.widget.size()
}
fn tag(&self) -> tree::Tag {
diff --git a/core/src/keyboard.rs b/core/src/keyboard.rs
index 4c6ca08d..b810ccb0 100644
--- a/core/src/keyboard.rs
+++ b/core/src/keyboard.rs
@@ -1,8 +1,11 @@
//! Listen to keyboard events.
+pub mod key;
+
mod event;
-mod key_code;
+mod location;
mod modifiers;
pub use event::Event;
-pub use key_code::KeyCode;
+pub use key::Key;
+pub use location::Location;
pub use modifiers::Modifiers;
diff --git a/core/src/keyboard/event.rs b/core/src/keyboard/event.rs
index 016761af..1eb42334 100644
--- a/core/src/keyboard/event.rs
+++ b/core/src/keyboard/event.rs
@@ -1,4 +1,5 @@
-use super::{KeyCode, Modifiers};
+use crate::keyboard::{Key, Location, Modifiers};
+use crate::SmolStr;
/// A keyboard event.
///
@@ -6,29 +7,35 @@ use super::{KeyCode, Modifiers};
/// additional events, feel free to [open an issue] and share your use case!_
///
/// [open an issue]: https://github.com/iced-rs/iced/issues
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Event {
/// A keyboard key was pressed.
KeyPressed {
- /// The key identifier
- key_code: KeyCode,
+ /// The key pressed.
+ key: Key,
- /// The state of the modifier keys
+ /// The location of the key.
+ location: Location,
+
+ /// The state of the modifier keys.
modifiers: Modifiers,
+
+ /// The text produced by the key press, if any.
+ text: Option<SmolStr>,
},
/// A keyboard key was released.
KeyReleased {
- /// The key identifier
- key_code: KeyCode,
+ /// The key released.
+ key: Key,
- /// The state of the modifier keys
+ /// The location of the key.
+ location: Location,
+
+ /// The state of the modifier keys.
modifiers: Modifiers,
},
- /// A unicode character was received.
- CharacterReceived(char),
-
/// The keyboard modifiers have changed.
ModifiersChanged(Modifiers),
}
diff --git a/core/src/keyboard/key.rs b/core/src/keyboard/key.rs
new file mode 100644
index 00000000..dbde5196
--- /dev/null
+++ b/core/src/keyboard/key.rs
@@ -0,0 +1,744 @@
+//! Identify keyboard keys.
+use crate::SmolStr;
+
+/// A key on the keyboard.
+///
+/// This is mostly the `Key` type found in [`winit`].
+///
+/// [`winit`]: https://docs.rs/winit/0.29.10/winit/keyboard/enum.Key.html
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum Key<C = SmolStr> {
+ /// A key with an established name.
+ Named(Named),
+
+ /// A key string that corresponds to the character typed by the user, taking into account the
+ /// user’s current locale setting, and any system-level keyboard mapping overrides that are in
+ /// effect.
+ Character(C),
+
+ /// An unidentified key.
+ Unidentified,
+}
+
+impl Key {
+ /// Convert `Key::Character(SmolStr)` to `Key::Character(&str)` so you can more easily match on
+ /// `Key`. All other variants remain unchanged.
+ pub fn as_ref(&self) -> Key<&str> {
+ match self {
+ Self::Named(named) => Key::Named(*named),
+ Self::Character(c) => Key::Character(c.as_ref()),
+ Self::Unidentified => Key::Unidentified,
+ }
+ }
+}
+
+/// A named key.
+///
+/// This is mostly the `NamedKey` type found in [`winit`].
+///
+/// [`winit`]: https://docs.rs/winit/0.29.10/winit/keyboard/enum.Key.html
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[allow(missing_docs)]
+pub enum Named {
+ /// The `Alt` (Alternative) key.
+ ///
+ /// This key enables the alternate modifier function for interpreting concurrent or subsequent
+ /// keyboard input. This key value is also used for the Apple <kbd>Option</kbd> key.
+ Alt,
+ /// The Alternate Graphics (<kbd>AltGr</kbd> or <kbd>AltGraph</kbd>) key.
+ ///
+ /// This key is used enable the ISO Level 3 shift modifier (the standard `Shift` key is the
+ /// level 2 modifier).
+ AltGraph,
+ /// The `Caps Lock` (Capital) key.
+ ///
+ /// Toggle capital character lock function for interpreting subsequent keyboard input event.
+ CapsLock,
+ /// The `Control` or `Ctrl` key.
+ ///
+ /// Used to enable control modifier function for interpreting concurrent or subsequent keyboard
+ /// input.
+ Control,
+ /// The Function switch `Fn` key. Activating this key simultaneously with another key changes
+ /// that key’s value to an alternate character or function. This key is often handled directly
+ /// in the keyboard hardware and does not usually generate key events.
+ Fn,
+ /// The Function-Lock (`FnLock` or `F-Lock`) key. Activating this key switches the mode of the
+ /// keyboard to changes some keys' values to an alternate character or function. This key is
+ /// often handled directly in the keyboard hardware and does not usually generate key events.
+ FnLock,
+ /// The `NumLock` or Number Lock key. Used to toggle numpad mode function for interpreting
+ /// subsequent keyboard input.
+ NumLock,
+ /// Toggle between scrolling and cursor movement modes.
+ ScrollLock,
+ /// Used to enable shift modifier function for interpreting concurrent or subsequent keyboard
+ /// input.
+ Shift,
+ /// The Symbol modifier key (used on some virtual keyboards).
+ Symbol,
+ SymbolLock,
+ // Legacy modifier key. Also called "Super" in certain places.
+ Meta,
+ // Legacy modifier key.
+ Hyper,
+ /// Used to enable "super" modifier function for interpreting concurrent or subsequent keyboard
+ /// input. This key value is used for the "Windows Logo" key and the Apple `Command` or `⌘` key.
+ ///
+ /// Note: In some contexts (e.g. the Web) this is referred to as the "Meta" key.
+ Super,
+ /// The `Enter` or `↵` key. Used to activate current selection or accept current input. This key
+ /// value is also used for the `Return` (Macintosh numpad) key. This key value is also used for
+ /// the Android `KEYCODE_DPAD_CENTER`.
+ Enter,
+ /// The Horizontal Tabulation `Tab` key.
+ Tab,
+ /// Used in text to insert a space between words. Usually located below the character keys.
+ Space,
+ /// Navigate or traverse downward. (`KEYCODE_DPAD_DOWN`)
+ ArrowDown,
+ /// Navigate or traverse leftward. (`KEYCODE_DPAD_LEFT`)
+ ArrowLeft,
+ /// Navigate or traverse rightward. (`KEYCODE_DPAD_RIGHT`)
+ ArrowRight,
+ /// Navigate or traverse upward. (`KEYCODE_DPAD_UP`)
+ ArrowUp,
+ /// The End key, used with keyboard entry to go to the end of content (`KEYCODE_MOVE_END`).
+ End,
+ /// The Home key, used with keyboard entry, to go to start of content (`KEYCODE_MOVE_HOME`).
+ /// For the mobile phone `Home` key (which goes to the phone’s main screen), use [`GoHome`].
+ ///
+ /// [`GoHome`]: Self::GoHome
+ Home,
+ /// Scroll down or display next page of content.
+ PageDown,
+ /// Scroll up or display previous page of content.
+ PageUp,
+ /// Used to remove the character to the left of the cursor. This key value is also used for
+ /// the key labeled `Delete` on MacOS keyboards.
+ Backspace,
+ /// Remove the currently selected input.
+ Clear,
+ /// Copy the current selection. (`APPCOMMAND_COPY`)
+ Copy,
+ /// The Cursor Select key.
+ CrSel,
+ /// Cut the current selection. (`APPCOMMAND_CUT`)
+ Cut,
+ /// Used to delete the character to the right of the cursor. This key value is also used for the
+ /// key labeled `Delete` on MacOS keyboards when `Fn` is active.
+ Delete,
+ /// The Erase to End of Field key. This key deletes all characters from the current cursor
+ /// position to the end of the current field.
+ EraseEof,
+ /// The Extend Selection (Exsel) key.
+ ExSel,
+ /// Toggle between text modes for insertion or overtyping.
+ /// (`KEYCODE_INSERT`)
+ Insert,
+ /// The Paste key. (`APPCOMMAND_PASTE`)
+ Paste,
+ /// Redo the last action. (`APPCOMMAND_REDO`)
+ Redo,
+ /// Undo the last action. (`APPCOMMAND_UNDO`)
+ Undo,
+ /// The Accept (Commit, OK) key. Accept current option or input method sequence conversion.
+ Accept,
+ /// Redo or repeat an action.
+ Again,
+ /// The Attention (Attn) key.
+ Attn,
+ Cancel,
+ /// Show the application’s context menu.
+ /// This key is commonly found between the right `Super` key and the right `Control` key.
+ ContextMenu,
+ /// The `Esc` key. This key was originally used to initiate an escape sequence, but is
+ /// now more generally used to exit or "escape" the current context, such as closing a dialog
+ /// or exiting full screen mode.
+ Escape,
+ Execute,
+ /// Open the Find dialog. (`APPCOMMAND_FIND`)
+ Find,
+ /// Open a help dialog or toggle display of help information. (`APPCOMMAND_HELP`,
+ /// `KEYCODE_HELP`)
+ Help,
+ /// Pause the current state or application (as appropriate).
+ ///
+ /// Note: Do not use this value for the `Pause` button on media controllers. Use `"MediaPause"`
+ /// instead.
+ Pause,
+ /// Play or resume the current state or application (as appropriate).
+ ///
+ /// Note: Do not use this value for the `Play` button on media controllers. Use `"MediaPlay"`
+ /// instead.
+ Play,
+ /// The properties (Props) key.
+ Props,
+ Select,
+ /// The ZoomIn key. (`KEYCODE_ZOOM_IN`)
+ ZoomIn,
+ /// The ZoomOut key. (`KEYCODE_ZOOM_OUT`)
+ ZoomOut,
+ /// The Brightness Down key. Typically controls the display brightness.
+ /// (`KEYCODE_BRIGHTNESS_DOWN`)
+ BrightnessDown,
+ /// The Brightness Up key. Typically controls the display brightness. (`KEYCODE_BRIGHTNESS_UP`)
+ BrightnessUp,
+ /// Toggle removable media to eject (open) and insert (close) state. (`KEYCODE_MEDIA_EJECT`)
+ Eject,
+ LogOff,
+ /// Toggle power state. (`KEYCODE_POWER`)
+ /// Note: Note: Some devices might not expose this key to the operating environment.
+ Power,
+ /// The `PowerOff` key. Sometime called `PowerDown`.
+ PowerOff,
+ /// Initiate print-screen function.
+ PrintScreen,
+ /// The Hibernate key. This key saves the current state of the computer to disk so that it can
+ /// be restored. The computer will then shutdown.
+ Hibernate,
+ /// The Standby key. This key turns off the display and places the computer into a low-power
+ /// mode without completely shutting down. It is sometimes labelled `Suspend` or `Sleep` key.
+ /// (`KEYCODE_SLEEP`)
+ Standby,
+ /// The WakeUp key. (`KEYCODE_WAKEUP`)
+ WakeUp,
+ /// Initate the multi-candidate mode.
+ AllCandidates,
+ Alphanumeric,
+ /// Initiate the Code Input mode to allow characters to be entered by
+ /// their code points.
+ CodeInput,
+ /// The Compose key, also known as "Multi_key" on the X Window System. This key acts in a
+ /// manner similar to a dead key, triggering a mode where subsequent key presses are combined to
+ /// produce a different character.
+ Compose,
+ /// Convert the current input method sequence.
+ Convert,
+ /// The Final Mode `Final` key used on some Asian keyboards, to enable the final mode for IMEs.
+ FinalMode,
+ /// Switch to the first character group. (ISO/IEC 9995)
+ GroupFirst,
+ /// Switch to the last character group. (ISO/IEC 9995)
+ GroupLast,
+ /// Switch to the next character group. (ISO/IEC 9995)
+ GroupNext,
+ /// Switch to the previous character group. (ISO/IEC 9995)
+ GroupPrevious,
+ /// Toggle between or cycle through input modes of IMEs.
+ ModeChange,
+ NextCandidate,
+ /// Accept current input method sequence without
+ /// conversion in IMEs.
+ NonConvert,
+ PreviousCandidate,
+ Process,
+ SingleCandidate,
+ /// Toggle between Hangul and English modes.
+ HangulMode,
+ HanjaMode,
+ JunjaMode,
+ /// The Eisu key. This key may close the IME, but its purpose is defined by the current IME.
+ /// (`KEYCODE_EISU`)
+ Eisu,
+ /// The (Half-Width) Characters key.
+ Hankaku,
+ /// The Hiragana (Japanese Kana characters) key.
+ Hiragana,
+ /// The Hiragana/Katakana toggle key. (`KEYCODE_KATAKANA_HIRAGANA`)
+ HiraganaKatakana,
+ /// The Kana Mode (Kana Lock) key. This key is used to enter hiragana mode (typically from
+ /// romaji mode).
+ KanaMode,
+ /// The Kanji (Japanese name for ideographic characters of Chinese origin) Mode key. This key is
+ /// typically used to switch to a hiragana keyboard for the purpose of converting input into
+ /// kanji. (`KEYCODE_KANA`)
+ KanjiMode,
+ /// The Katakana (Japanese Kana characters) key.
+ Katakana,
+ /// The Roman characters function key.
+ Romaji,
+ /// The Zenkaku (Full-Width) Characters key.
+ Zenkaku,
+ /// The Zenkaku/Hankaku (full-width/half-width) toggle key. (`KEYCODE_ZENKAKU_HANKAKU`)
+ ZenkakuHankaku,
+ /// General purpose virtual function key, as index 1.
+ Soft1,
+ /// General purpose virtual function key, as index 2.
+ Soft2,
+ /// General purpose virtual function key, as index 3.
+ Soft3,
+ /// General purpose virtual function key, as index 4.
+ Soft4,
+ /// Select next (numerically or logically) lower channel. (`APPCOMMAND_MEDIA_CHANNEL_DOWN`,
+ /// `KEYCODE_CHANNEL_DOWN`)
+ ChannelDown,
+ /// Select next (numerically or logically) higher channel. (`APPCOMMAND_MEDIA_CHANNEL_UP`,
+ /// `KEYCODE_CHANNEL_UP`)
+ ChannelUp,
+ /// Close the current document or message (Note: This doesn’t close the application).
+ /// (`APPCOMMAND_CLOSE`)
+ Close,
+ /// Open an editor to forward the current message. (`APPCOMMAND_FORWARD_MAIL`)
+ MailForward,
+ /// Open an editor to reply to the current message. (`APPCOMMAND_REPLY_TO_MAIL`)
+ MailReply,
+ /// Send the current message. (`APPCOMMAND_SEND_MAIL`)
+ MailSend,
+ /// Close the current media, for example to close a CD or DVD tray. (`KEYCODE_MEDIA_CLOSE`)
+ MediaClose,
+ /// Initiate or continue forward playback at faster than normal speed, or increase speed if
+ /// already fast forwarding. (`APPCOMMAND_MEDIA_FAST_FORWARD`, `KEYCODE_MEDIA_FAST_FORWARD`)
+ MediaFastForward,
+ /// Pause the currently playing media. (`APPCOMMAND_MEDIA_PAUSE`, `KEYCODE_MEDIA_PAUSE`)
+ ///
+ /// Note: Media controller devices should use this value rather than `"Pause"` for their pause
+ /// keys.
+ MediaPause,
+ /// Initiate or continue media playback at normal speed, if not currently playing at normal
+ /// speed. (`APPCOMMAND_MEDIA_PLAY`, `KEYCODE_MEDIA_PLAY`)
+ MediaPlay,
+ /// Toggle media between play and pause states. (`APPCOMMAND_MEDIA_PLAY_PAUSE`,
+ /// `KEYCODE_MEDIA_PLAY_PAUSE`)
+ MediaPlayPause,
+ /// Initiate or resume recording of currently selected media. (`APPCOMMAND_MEDIA_RECORD`,
+ /// `KEYCODE_MEDIA_RECORD`)
+ MediaRecord,
+ /// Initiate or continue reverse playback at faster than normal speed, or increase speed if
+ /// already rewinding. (`APPCOMMAND_MEDIA_REWIND`, `KEYCODE_MEDIA_REWIND`)
+ MediaRewind,
+ /// Stop media playing, pausing, forwarding, rewinding, or recording, if not already stopped.
+ /// (`APPCOMMAND_MEDIA_STOP`, `KEYCODE_MEDIA_STOP`)
+ MediaStop,
+ /// Seek to next media or program track. (`APPCOMMAND_MEDIA_NEXTTRACK`, `KEYCODE_MEDIA_NEXT`)
+ MediaTrackNext,
+ /// Seek to previous media or program track. (`APPCOMMAND_MEDIA_PREVIOUSTRACK`,
+ /// `KEYCODE_MEDIA_PREVIOUS`)
+ MediaTrackPrevious,
+ /// Open a new document or message. (`APPCOMMAND_NEW`)
+ New,
+ /// Open an existing document or message. (`APPCOMMAND_OPEN`)
+ Open,
+ /// Print the current document or message. (`APPCOMMAND_PRINT`)
+ Print,
+ /// Save the current document or message. (`APPCOMMAND_SAVE`)
+ Save,
+ /// Spellcheck the current document or selection. (`APPCOMMAND_SPELL_CHECK`)
+ SpellCheck,
+ /// The `11` key found on media numpads that
+ /// have buttons from `1` ... `12`.
+ Key11,
+ /// The `12` key found on media numpads that
+ /// have buttons from `1` ... `12`.
+ Key12,
+ /// Adjust audio balance leftward. (`VK_AUDIO_BALANCE_LEFT`)
+ AudioBalanceLeft,
+ /// Adjust audio balance rightward. (`VK_AUDIO_BALANCE_RIGHT`)
+ AudioBalanceRight,
+ /// Decrease audio bass boost or cycle down through bass boost states. (`APPCOMMAND_BASS_DOWN`,
+ /// `VK_BASS_BOOST_DOWN`)
+ AudioBassBoostDown,
+ /// Toggle bass boost on/off. (`APPCOMMAND_BASS_BOOST`)
+ AudioBassBoostToggle,
+ /// Increase audio bass boost or cycle up through bass boost states. (`APPCOMMAND_BASS_UP`,
+ /// `VK_BASS_BOOST_UP`)
+ AudioBassBoostUp,
+ /// Adjust audio fader towards front. (`VK_FADER_FRONT`)
+ AudioFaderFront,
+ /// Adjust audio fader towards rear. (`VK_FADER_REAR`)
+ AudioFaderRear,
+ /// Advance surround audio mode to next available mode. (`VK_SURROUND_MODE_NEXT`)
+ AudioSurroundModeNext,
+ /// Decrease treble. (`APPCOMMAND_TREBLE_DOWN`)
+ AudioTrebleDown,
+ /// Increase treble. (`APPCOMMAND_TREBLE_UP`)
+ AudioTrebleUp,
+ /// Decrease audio volume. (`APPCOMMAND_VOLUME_DOWN`, `KEYCODE_VOLUME_DOWN`)
+ AudioVolumeDown,
+ /// Increase audio volume. (`APPCOMMAND_VOLUME_UP`, `KEYCODE_VOLUME_UP`)
+ AudioVolumeUp,
+ /// Toggle between muted state and prior volume level. (`APPCOMMAND_VOLUME_MUTE`,
+ /// `KEYCODE_VOLUME_MUTE`)
+ AudioVolumeMute,
+ /// Toggle the microphone on/off. (`APPCOMMAND_MIC_ON_OFF_TOGGLE`)
+ MicrophoneToggle,
+ /// Decrease microphone volume. (`APPCOMMAND_MICROPHONE_VOLUME_DOWN`)
+ MicrophoneVolumeDown,
+ /// Increase microphone volume. (`APPCOMMAND_MICROPHONE_VOLUME_UP`)
+ MicrophoneVolumeUp,
+ /// Mute the microphone. (`APPCOMMAND_MICROPHONE_VOLUME_MUTE`, `KEYCODE_MUTE`)
+ MicrophoneVolumeMute,
+ /// Show correction list when a word is incorrectly identified. (`APPCOMMAND_CORRECTION_LIST`)
+ SpeechCorrectionList,
+ /// Toggle between dictation mode and command/control mode.
+ /// (`APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE`)
+ SpeechInputToggle,
+ /// The first generic "LaunchApplication" key. This is commonly associated with launching "My
+ /// Computer", and may have a computer symbol on the key. (`APPCOMMAND_LAUNCH_APP1`)
+ LaunchApplication1,
+ /// The second generic "LaunchApplication" key. This is commonly associated with launching
+ /// "Calculator", and may have a calculator symbol on the key. (`APPCOMMAND_LAUNCH_APP2`,
+ /// `KEYCODE_CALCULATOR`)
+ LaunchApplication2,
+ /// The "Calendar" key. (`KEYCODE_CALENDAR`)
+ LaunchCalendar,
+ /// The "Contacts" key. (`KEYCODE_CONTACTS`)
+ LaunchContacts,
+ /// The "Mail" key. (`APPCOMMAND_LAUNCH_MAIL`)
+ LaunchMail,
+ /// The "Media Player" key. (`APPCOMMAND_LAUNCH_MEDIA_SELECT`)
+ LaunchMediaPlayer,
+ LaunchMusicPlayer,
+ LaunchPhone,
+ LaunchScreenSaver,
+ LaunchSpreadsheet,
+ LaunchWebBrowser,
+ LaunchWebCam,
+ LaunchWordProcessor,
+ /// Navigate to previous content or page in current history. (`APPCOMMAND_BROWSER_BACKWARD`)
+ BrowserBack,
+ /// Open the list of browser favorites. (`APPCOMMAND_BROWSER_FAVORITES`)
+ BrowserFavorites,
+ /// Navigate to next content or page in current history. (`APPCOMMAND_BROWSER_FORWARD`)
+ BrowserForward,
+ /// Go to the user’s preferred home page. (`APPCOMMAND_BROWSER_HOME`)
+ BrowserHome,
+ /// Refresh the current page or content. (`APPCOMMAND_BROWSER_REFRESH`)
+ BrowserRefresh,
+ /// Call up the user’s preferred search page. (`APPCOMMAND_BROWSER_SEARCH`)
+ BrowserSearch,
+ /// Stop loading the current page or content. (`APPCOMMAND_BROWSER_STOP`)
+ BrowserStop,
+ /// The Application switch key, which provides a list of recent apps to switch between.
+ /// (`KEYCODE_APP_SWITCH`)
+ AppSwitch,
+ /// The Call key. (`KEYCODE_CALL`)
+ Call,
+ /// The Camera key. (`KEYCODE_CAMERA`)
+ Camera,
+ /// The Camera focus key. (`KEYCODE_FOCUS`)
+ CameraFocus,
+ /// The End Call key. (`KEYCODE_ENDCALL`)
+ EndCall,
+ /// The Back key. (`KEYCODE_BACK`)
+ GoBack,
+ /// The Home key, which goes to the phone’s main screen. (`KEYCODE_HOME`)
+ GoHome,
+ /// The Headset Hook key. (`KEYCODE_HEADSETHOOK`)
+ HeadsetHook,
+ LastNumberRedial,
+ /// The Notification key. (`KEYCODE_NOTIFICATION`)
+ Notification,
+ /// Toggle between manner mode state: silent, vibrate, ring, ... (`KEYCODE_MANNER_MODE`)
+ MannerMode,
+ VoiceDial,
+ /// Switch to viewing TV. (`KEYCODE_TV`)
+ TV,
+ /// TV 3D Mode. (`KEYCODE_3D_MODE`)
+ TV3DMode,
+ /// Toggle between antenna and cable input. (`KEYCODE_TV_ANTENNA_CABLE`)
+ TVAntennaCable,
+ /// Audio description. (`KEYCODE_TV_AUDIO_DESCRIPTION`)
+ TVAudioDescription,
+ /// Audio description mixing volume down. (`KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN`)
+ TVAudioDescriptionMixDown,
+ /// Audio description mixing volume up. (`KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP`)
+ TVAudioDescriptionMixUp,
+ /// Contents menu. (`KEYCODE_TV_CONTENTS_MENU`)
+ TVContentsMenu,
+ /// Contents menu. (`KEYCODE_TV_DATA_SERVICE`)
+ TVDataService,
+ /// Switch the input mode on an external TV. (`KEYCODE_TV_INPUT`)
+ TVInput,
+ /// Switch to component input #1. (`KEYCODE_TV_INPUT_COMPONENT_1`)
+ TVInputComponent1,
+ /// Switch to component input #2. (`KEYCODE_TV_INPUT_COMPONENT_2`)
+ TVInputComponent2,
+ /// Switch to composite input #1. (`KEYCODE_TV_INPUT_COMPOSITE_1`)
+ TVInputComposite1,
+ /// Switch to composite input #2. (`KEYCODE_TV_INPUT_COMPOSITE_2`)
+ TVInputComposite2,
+ /// Switch to HDMI input #1. (`KEYCODE_TV_INPUT_HDMI_1`)
+ TVInputHDMI1,
+ /// Switch to HDMI input #2. (`KEYCODE_TV_INPUT_HDMI_2`)
+ TVInputHDMI2,
+ /// Switch to HDMI input #3. (`KEYCODE_TV_INPUT_HDMI_3`)
+ TVInputHDMI3,
+ /// Switch to HDMI input #4. (`KEYCODE_TV_INPUT_HDMI_4`)
+ TVInputHDMI4,
+ /// Switch to VGA input #1. (`KEYCODE_TV_INPUT_VGA_1`)
+ TVInputVGA1,
+ /// Media context menu. (`KEYCODE_TV_MEDIA_CONTEXT_MENU`)
+ TVMediaContext,
+ /// Toggle network. (`KEYCODE_TV_NETWORK`)
+ TVNetwork,
+ /// Number entry. (`KEYCODE_TV_NUMBER_ENTRY`)
+ TVNumberEntry,
+ /// Toggle the power on an external TV. (`KEYCODE_TV_POWER`)
+ TVPower,
+ /// Radio. (`KEYCODE_TV_RADIO_SERVICE`)
+ TVRadioService,
+ /// Satellite. (`KEYCODE_TV_SATELLITE`)
+ TVSatellite,
+ /// Broadcast Satellite. (`KEYCODE_TV_SATELLITE_BS`)
+ TVSatelliteBS,
+ /// Communication Satellite. (`KEYCODE_TV_SATELLITE_CS`)
+ TVSatelliteCS,
+ /// Toggle between available satellites. (`KEYCODE_TV_SATELLITE_SERVICE`)
+ TVSatelliteToggle,
+ /// Analog Terrestrial. (`KEYCODE_TV_TERRESTRIAL_ANALOG`)
+ TVTerrestrialAnalog,
+ /// Digital Terrestrial. (`KEYCODE_TV_TERRESTRIAL_DIGITAL`)
+ TVTerrestrialDigital,
+ /// Timer programming. (`KEYCODE_TV_TIMER_PROGRAMMING`)
+ TVTimer,
+ /// Switch the input mode on an external AVR (audio/video receiver). (`KEYCODE_AVR_INPUT`)
+ AVRInput,
+ /// Toggle the power on an external AVR (audio/video receiver). (`KEYCODE_AVR_POWER`)
+ AVRPower,
+ /// General purpose color-coded media function key, as index 0 (red). (`VK_COLORED_KEY_0`,
+ /// `KEYCODE_PROG_RED`)
+ ColorF0Red,
+ /// General purpose color-coded media function key, as index 1 (green). (`VK_COLORED_KEY_1`,
+ /// `KEYCODE_PROG_GREEN`)
+ ColorF1Green,
+ /// General purpose color-coded media function key, as index 2 (yellow). (`VK_COLORED_KEY_2`,
+ /// `KEYCODE_PROG_YELLOW`)
+ ColorF2Yellow,
+ /// General purpose color-coded media function key, as index 3 (blue). (`VK_COLORED_KEY_3`,
+ /// `KEYCODE_PROG_BLUE`)
+ ColorF3Blue,
+ /// General purpose color-coded media function key, as index 4 (grey). (`VK_COLORED_KEY_4`)
+ ColorF4Grey,
+ /// General purpose color-coded media function key, as index 5 (brown). (`VK_COLORED_KEY_5`)
+ ColorF5Brown,
+ /// Toggle the display of Closed Captions. (`VK_CC`, `KEYCODE_CAPTIONS`)
+ ClosedCaptionToggle,
+ /// Adjust brightness of device, by toggling between or cycling through states. (`VK_DIMMER`)
+ Dimmer,
+ /// Swap video sources. (`VK_DISPLAY_SWAP`)
+ DisplaySwap,
+ /// Select Digital Video Rrecorder. (`KEYCODE_DVR`)
+ DVR,
+ /// Exit the current application. (`VK_EXIT`)
+ Exit,
+ /// Clear program or content stored as favorite 0. (`VK_CLEAR_FAVORITE_0`)
+ FavoriteClear0,
+ /// Clear program or content stored as favorite 1. (`VK_CLEAR_FAVORITE_1`)
+ FavoriteClear1,
+ /// Clear program or content stored as favorite 2. (`VK_CLEAR_FAVORITE_2`)
+ FavoriteClear2,
+ /// Clear program or content stored as favorite 3. (`VK_CLEAR_FAVORITE_3`)
+ FavoriteClear3,
+ /// Select (recall) program or content stored as favorite 0. (`VK_RECALL_FAVORITE_0`)
+ FavoriteRecall0,
+ /// Select (recall) program or content stored as favorite 1. (`VK_RECALL_FAVORITE_1`)
+ FavoriteRecall1,
+ /// Select (recall) program or content stored as favorite 2. (`VK_RECALL_FAVORITE_2`)
+ FavoriteRecall2,
+ /// Select (recall) program or content stored as favorite 3. (`VK_RECALL_FAVORITE_3`)
+ FavoriteRecall3,
+ /// Store current program or content as favorite 0. (`VK_STORE_FAVORITE_0`)
+ FavoriteStore0,
+ /// Store current program or content as favorite 1. (`VK_STORE_FAVORITE_1`)
+ FavoriteStore1,
+ /// Store current program or content as favorite 2. (`VK_STORE_FAVORITE_2`)
+ FavoriteStore2,
+ /// Store current program or content as favorite 3. (`VK_STORE_FAVORITE_3`)
+ FavoriteStore3,
+ /// Toggle display of program or content guide. (`VK_GUIDE`, `KEYCODE_GUIDE`)
+ Guide,
+ /// If guide is active and displayed, then display next day’s content. (`VK_NEXT_DAY`)
+ GuideNextDay,
+ /// If guide is active and displayed, then display previous day’s content. (`VK_PREV_DAY`)
+ GuidePreviousDay,
+ /// Toggle display of information about currently selected context or media. (`VK_INFO`,
+ /// `KEYCODE_INFO`)
+ Info,
+ /// Toggle instant replay. (`VK_INSTANT_REPLAY`)
+ InstantReplay,
+ /// Launch linked content, if available and appropriate. (`VK_LINK`)
+ Link,
+ /// List the current program. (`VK_LIST`)
+ ListProgram,
+ /// Toggle display listing of currently available live content or programs. (`VK_LIVE`)
+ LiveContent,
+ /// Lock or unlock current content or program. (`VK_LOCK`)
+ Lock,
+ /// Show a list of media applications: audio/video players and image viewers. (`VK_APPS`)
+ ///
+ /// Note: Do not confuse this key value with the Windows' `VK_APPS` / `VK_CONTEXT_MENU` key,
+ /// which is encoded as `"ContextMenu"`.
+ MediaApps,
+ /// Audio track key. (`KEYCODE_MEDIA_AUDIO_TRACK`)
+ MediaAudioTrack,
+ /// Select previously selected channel or media. (`VK_LAST`, `KEYCODE_LAST_CHANNEL`)
+ MediaLast,
+ /// Skip backward to next content or program. (`KEYCODE_MEDIA_SKIP_BACKWARD`)
+ MediaSkipBackward,
+ /// Skip forward to next content or program. (`VK_SKIP`, `KEYCODE_MEDIA_SKIP_FORWARD`)
+ MediaSkipForward,
+ /// Step backward to next content or program. (`KEYCODE_MEDIA_STEP_BACKWARD`)
+ MediaStepBackward,
+ /// Step forward to next content or program. (`KEYCODE_MEDIA_STEP_FORWARD`)
+ MediaStepForward,
+ /// Media top menu. (`KEYCODE_MEDIA_TOP_MENU`)
+ MediaTopMenu,
+ /// Navigate in. (`KEYCODE_NAVIGATE_IN`)
+ NavigateIn,
+ /// Navigate to next key. (`KEYCODE_NAVIGATE_NEXT`)
+ NavigateNext,
+ /// Navigate out. (`KEYCODE_NAVIGATE_OUT`)
+ NavigateOut,
+ /// Navigate to previous key. (`KEYCODE_NAVIGATE_PREVIOUS`)
+ NavigatePrevious,
+ /// Cycle to next favorite channel (in favorites list). (`VK_NEXT_FAVORITE_CHANNEL`)
+ NextFavoriteChannel,
+ /// Cycle to next user profile (if there are multiple user profiles). (`VK_USER`)
+ NextUserProfile,
+ /// Access on-demand content or programs. (`VK_ON_DEMAND`)
+ OnDemand,
+ /// Pairing key to pair devices. (`KEYCODE_PAIRING`)
+ Pairing,
+ /// Move picture-in-picture window down. (`VK_PINP_DOWN`)
+ PinPDown,
+ /// Move picture-in-picture window. (`VK_PINP_MOVE`)
+ PinPMove,
+ /// Toggle display of picture-in-picture window. (`VK_PINP_TOGGLE`)
+ PinPToggle,
+ /// Move picture-in-picture window up. (`VK_PINP_UP`)
+ PinPUp,
+ /// Decrease media playback speed. (`VK_PLAY_SPEED_DOWN`)
+ PlaySpeedDown,
+ /// Reset playback to normal speed. (`VK_PLAY_SPEED_RESET`)
+ PlaySpeedReset,
+ /// Increase media playback speed. (`VK_PLAY_SPEED_UP`)
+ PlaySpeedUp,
+ /// Toggle random media or content shuffle mode. (`VK_RANDOM_TOGGLE`)
+ RandomToggle,
+ /// Not a physical key, but this key code is sent when the remote control battery is low.
+ /// (`VK_RC_LOW_BATTERY`)
+ RcLowBattery,
+ /// Toggle or cycle between media recording speeds. (`VK_RECORD_SPEED_NEXT`)
+ RecordSpeedNext,
+ /// Toggle RF (radio frequency) input bypass mode (pass RF input directly to the RF output).
+ /// (`VK_RF_BYPASS`)
+ RfBypass,
+ /// Toggle scan channels mode. (`VK_SCAN_CHANNELS_TOGGLE`)
+ ScanChannelsToggle,
+ /// Advance display screen mode to next available mode. (`VK_SCREEN_MODE_NEXT`)
+ ScreenModeNext,
+ /// Toggle display of device settings screen. (`VK_SETTINGS`, `KEYCODE_SETTINGS`)
+ Settings,
+ /// Toggle split screen mode. (`VK_SPLIT_SCREEN_TOGGLE`)
+ SplitScreenToggle,
+ /// Switch the input mode on an external STB (set top box). (`KEYCODE_STB_INPUT`)
+ STBInput,
+ /// Toggle the power on an external STB (set top box). (`KEYCODE_STB_POWER`)
+ STBPower,
+ /// Toggle display of subtitles, if available. (`VK_SUBTITLE`)
+ Subtitle,
+ /// Toggle display of teletext, if available (`VK_TELETEXT`, `KEYCODE_TV_TELETEXT`).
+ Teletext,
+ /// Advance video mode to next available mode. (`VK_VIDEO_MODE_NEXT`)
+ VideoModeNext,
+ /// Cause device to identify itself in some manner, e.g., audibly or visibly. (`VK_WINK`)
+ Wink,
+ /// Toggle between full-screen and scaled content, or alter magnification level. (`VK_ZOOM`,
+ /// `KEYCODE_TV_ZOOM_MODE`)
+ ZoomToggle,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F1,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F2,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F3,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F4,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F5,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F6,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F7,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F8,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F9,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F10,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F11,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F12,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F13,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F14,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F15,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F16,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F17,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F18,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F19,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F20,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F21,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F22,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F23,
+ /// General-purpose function key.
+ /// Usually found at the top of the keyboard.
+ F24,
+ /// General-purpose function key.
+ F25,
+ /// General-purpose function key.
+ F26,
+ /// General-purpose function key.
+ F27,
+ /// General-purpose function key.
+ F28,
+ /// General-purpose function key.
+ F29,
+ /// General-purpose function key.
+ F30,
+ /// General-purpose function key.
+ F31,
+ /// General-purpose function key.
+ F32,
+ /// General-purpose function key.
+ F33,
+ /// General-purpose function key.
+ F34,
+ /// General-purpose function key.
+ F35,
+}
diff --git a/core/src/keyboard/key_code.rs b/core/src/keyboard/key_code.rs
deleted file mode 100644
index 74ead170..00000000
--- a/core/src/keyboard/key_code.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-/// The symbolic name of a keyboard key.
-///
-/// This is mostly the `KeyCode` type found in [`winit`].
-///
-/// [`winit`]: https://docs.rs/winit/0.20.0-alpha3/winit/
-#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
-#[repr(u32)]
-#[allow(missing_docs)]
-pub enum KeyCode {
- /// The '1' key over the letters.
- Key1,
- /// The '2' key over the letters.
- Key2,
- /// The '3' key over the letters.
- Key3,
- /// The '4' key over the letters.
- Key4,
- /// The '5' key over the letters.
- Key5,
- /// The '6' key over the letters.
- Key6,
- /// The '7' key over the letters.
- Key7,
- /// The '8' key over the letters.
- Key8,
- /// The '9' key over the letters.
- Key9,
- /// The '0' key over the 'O' and 'P' keys.
- Key0,
-
- A,
- B,
- C,
- D,
- E,
- F,
- G,
- H,
- I,
- J,
- K,
- L,
- M,
- N,
- O,
- P,
- Q,
- R,
- S,
- T,
- U,
- V,
- W,
- X,
- Y,
- Z,
-
- /// The Escape key, next to F1.
- Escape,
-
- F1,
- F2,
- F3,
- F4,
- F5,
- F6,
- F7,
- F8,
- F9,
- F10,
- F11,
- F12,
- F13,
- F14,
- F15,
- F16,
- F17,
- F18,
- F19,
- F20,
- F21,
- F22,
- F23,
- F24,
-
- /// Print Screen/SysRq.
- Snapshot,
- /// Scroll Lock.
- Scroll,
- /// Pause/Break key, next to Scroll lock.
- Pause,
-
- /// `Insert`, next to Backspace.
- Insert,
- Home,
- Delete,
- End,
- PageDown,
- PageUp,
-
- Left,
- Up,
- Right,
- Down,
-
- /// The Backspace key, right over Enter.
- Backspace,
- /// The Enter key.
- Enter,
- /// The space bar.
- Space,
-
- /// The "Compose" key on Linux.
- Compose,
-
- Caret,
-
- Numlock,
- Numpad0,
- Numpad1,
- Numpad2,
- Numpad3,
- Numpad4,
- Numpad5,
- Numpad6,
- Numpad7,
- Numpad8,
- Numpad9,
- NumpadAdd,
- NumpadDivide,
- NumpadDecimal,
- NumpadComma,
- NumpadEnter,
- NumpadEquals,
- NumpadMultiply,
- NumpadSubtract,
-
- AbntC1,
- AbntC2,
- Apostrophe,
- Apps,
- Asterisk,
- At,
- Ax,
- Backslash,
- Calculator,
- Capital,
- Colon,
- Comma,
- Convert,
- Equals,
- Grave,
- Kana,
- Kanji,
- LAlt,
- LBracket,
- LControl,
- LShift,
- LWin,
- Mail,
- MediaSelect,
- MediaStop,
- Minus,
- Mute,
- MyComputer,
- NavigateForward, // also called "Next"
- NavigateBackward, // also called "Prior"
- NextTrack,
- NoConvert,
- OEM102,
- Period,
- PlayPause,
- Plus,
- Power,
- PrevTrack,
- RAlt,
- RBracket,
- RControl,
- RShift,
- RWin,
- Semicolon,
- Slash,
- Sleep,
- Stop,
- Sysrq,
- Tab,
- Underline,
- Unlabeled,
- VolumeDown,
- VolumeUp,
- Wake,
- WebBack,
- WebFavorites,
- WebForward,
- WebHome,
- WebRefresh,
- WebSearch,
- WebStop,
- Yen,
- Copy,
- Paste,
- Cut,
-}
diff --git a/core/src/keyboard/location.rs b/core/src/keyboard/location.rs
new file mode 100644
index 00000000..feff0820
--- /dev/null
+++ b/core/src/keyboard/location.rs
@@ -0,0 +1,12 @@
+/// The location of a key on the keyboard.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Location {
+ /// The standard group of keys on the keyboard.
+ Standard,
+ /// The left side of the keyboard.
+ Left,
+ /// The right side of the keyboard.
+ Right,
+ /// The numpad of the keyboard.
+ Numpad,
+}
diff --git a/core/src/layout.rs b/core/src/layout.rs
index caf315b6..95720aba 100644
--- a/core/src/layout.rs
+++ b/core/src/layout.rs
@@ -7,7 +7,7 @@ pub mod flex;
pub use limits::Limits;
pub use node::Node;
-use crate::{Point, Rectangle, Size, Vector};
+use crate::{Length, Padding, Point, Rectangle, Size, Vector};
/// The bounds of a [`Node`] and its children, using absolute coordinates.
#[derive(Debug, Clone, Copy)]
@@ -71,12 +71,12 @@ pub fn next_to_each_other(
left: impl FnOnce(&Limits) -> Node,
right: impl FnOnce(&Limits) -> Node,
) -> Node {
- let mut left_node = left(limits);
+ let left_node = left(limits);
let left_size = left_node.size();
let right_limits = limits.shrink(Size::new(left_size.width + spacing, 0.0));
- let mut right_node = right(&right_limits);
+ let right_node = right(&right_limits);
let right_size = right_node.size();
let (left_y, right_y) = if left_size.height > right_size.height {
@@ -85,14 +85,106 @@ pub fn next_to_each_other(
((right_size.height - left_size.height) / 2.0, 0.0)
};
- left_node.move_to(Point::new(0.0, left_y));
- right_node.move_to(Point::new(left_size.width + spacing, right_y));
-
Node::with_children(
Size::new(
left_size.width + spacing + right_size.width,
left_size.height.max(right_size.height),
),
- vec![left_node, right_node],
+ vec![
+ left_node.move_to(Point::new(0.0, left_y)),
+ right_node.move_to(Point::new(left_size.width + spacing, right_y)),
+ ],
+ )
+}
+
+/// Computes the resulting [`Node`] that fits the [`Limits`] given
+/// some width and height requirements and no intrinsic size.
+pub fn atomic(
+ limits: &Limits,
+ width: impl Into<Length>,
+ height: impl Into<Length>,
+) -> Node {
+ let width = width.into();
+ let height = height.into();
+
+ Node::new(limits.resolve(width, height, Size::ZERO))
+}
+
+/// Computes the resulting [`Node`] that fits the [`Limits`] given
+/// some width and height requirements and a closure that produces
+/// the intrinsic [`Size`] inside the given [`Limits`].
+pub fn sized(
+ limits: &Limits,
+ width: impl Into<Length>,
+ height: impl Into<Length>,
+ f: impl FnOnce(&Limits) -> Size,
+) -> Node {
+ let width = width.into();
+ let height = height.into();
+
+ let limits = limits.width(width).height(height);
+ let intrinsic_size = f(&limits);
+
+ Node::new(limits.resolve(width, height, intrinsic_size))
+}
+
+/// Computes the resulting [`Node`] that fits the [`Limits`] given
+/// some width and height requirements and a closure that produces
+/// the content [`Node`] inside the given [`Limits`].
+pub fn contained(
+ limits: &Limits,
+ width: impl Into<Length>,
+ height: impl Into<Length>,
+ f: impl FnOnce(&Limits) -> Node,
+) -> Node {
+ let width = width.into();
+ let height = height.into();
+
+ let limits = limits.width(width).height(height);
+ let content = f(&limits);
+
+ Node::with_children(
+ limits.resolve(width, height, content.size()),
+ vec![content],
+ )
+}
+
+/// Computes the [`Node`] that fits the [`Limits`] given some width, height, and
+/// [`Padding`] requirements and a closure that produces the content [`Node`]
+/// inside the given [`Limits`].
+pub fn padded(
+ limits: &Limits,
+ width: impl Into<Length>,
+ height: impl Into<Length>,
+ padding: impl Into<Padding>,
+ layout: impl FnOnce(&Limits) -> Node,
+) -> Node {
+ positioned(limits, width, height, padding, layout, |content, _| content)
+}
+
+/// Computes a [`padded`] [`Node`] with a positioning step.
+pub fn positioned(
+ limits: &Limits,
+ width: impl Into<Length>,
+ height: impl Into<Length>,
+ padding: impl Into<Padding>,
+ layout: impl FnOnce(&Limits) -> Node,
+ position: impl FnOnce(Node, Size) -> Node,
+) -> Node {
+ let width = width.into();
+ let height = height.into();
+ let padding = padding.into();
+
+ let limits = limits.width(width).height(height);
+ let content = layout(&limits.shrink(padding));
+ let padding = padding.fit(content.size(), limits.max());
+
+ let size = limits
+ .shrink(padding)
+ .resolve(width, height, content.size());
+
+ Node::with_children(
+ size.expand(padding),
+ vec![position(content.move_to((padding.left, padding.top)), size)],
)
}
diff --git a/core/src/layout/flex.rs b/core/src/layout/flex.rs
index c02b63d8..3358ef3d 100644
--- a/core/src/layout/flex.rs
+++ b/core/src/layout/flex.rs
@@ -20,7 +20,7 @@ use crate::Element;
use crate::layout::{Limits, Node};
use crate::widget;
-use crate::{Alignment, Padding, Point, Size};
+use crate::{Alignment, Length, Padding, Point, Size};
/// The main axis of a flex layout.
#[derive(Debug)]
@@ -47,7 +47,7 @@ impl Axis {
}
}
- fn pack(&self, main: f32, cross: f32) -> (f32, f32) {
+ fn pack<T>(&self, main: T, cross: T) -> (T, T) {
match self {
Axis::Horizontal => (main, cross),
Axis::Vertical => (cross, main),
@@ -63,6 +63,8 @@ pub fn resolve<Message, Renderer>(
axis: Axis,
renderer: &Renderer,
limits: &Limits,
+ width: Length,
+ height: Length,
padding: Padding,
spacing: f32,
align_items: Alignment,
@@ -72,26 +74,64 @@ pub fn resolve<Message, Renderer>(
where
Renderer: crate::Renderer,
{
- let limits = limits.pad(padding);
+ let limits = limits.width(width).height(height).shrink(padding);
let total_spacing = spacing * items.len().saturating_sub(1) as f32;
let max_cross = axis.cross(limits.max());
- let mut fill_sum = 0;
- let mut cross = axis.cross(limits.min()).max(axis.cross(limits.fill()));
+ let mut fill_main_sum = 0;
+ let mut cross = match axis {
+ Axis::Horizontal => match height {
+ Length::Shrink => 0.0,
+ _ => max_cross,
+ },
+ Axis::Vertical => match width {
+ Length::Shrink => 0.0,
+ _ => max_cross,
+ },
+ };
+
let mut available = axis.main(limits.max()) - total_spacing;
let mut nodes: Vec<Node> = Vec::with_capacity(items.len());
nodes.resize(items.len(), Node::default());
for (i, (child, tree)) in items.iter().zip(trees.iter_mut()).enumerate() {
- let fill_factor = match axis {
- Axis::Horizontal => child.as_widget().width(),
- Axis::Vertical => child.as_widget().height(),
+ let (fill_main_factor, fill_cross_factor) = {
+ let size = child.as_widget().size();
+
+ axis.pack(size.width.fill_factor(), size.height.fill_factor())
+ };
+
+ if fill_main_factor == 0 {
+ if fill_cross_factor == 0 {
+ let (max_width, max_height) = axis.pack(available, max_cross);
+
+ let child_limits =
+ Limits::new(Size::ZERO, Size::new(max_width, max_height));
+
+ let layout =
+ child.as_widget().layout(tree, renderer, &child_limits);
+ let size = layout.size();
+
+ available -= axis.main(size);
+ cross = cross.max(axis.cross(size));
+
+ nodes[i] = layout;
+ }
+ } else {
+ fill_main_sum += fill_main_factor;
}
- .fill_factor();
+ }
- if fill_factor == 0 {
- let (max_width, max_height) = axis.pack(available, max_cross);
+ for (i, (child, tree)) in items.iter().zip(trees.iter_mut()).enumerate() {
+ let (fill_main_factor, fill_cross_factor) = {
+ let size = child.as_widget().size();
+
+ axis.pack(size.width.fill_factor(), size.height.fill_factor())
+ };
+
+ if fill_main_factor == 0 && fill_cross_factor != 0 {
+ let (max_width, max_height) = axis.pack(available, cross);
let child_limits =
Limits::new(Size::ZERO, Size::new(max_width, max_height));
@@ -101,34 +141,47 @@ where
let size = layout.size();
available -= axis.main(size);
- cross = cross.max(axis.cross(size));
+ cross = cross.max(axis.cross(layout.size()));
nodes[i] = layout;
- } else {
- fill_sum += fill_factor;
}
}
- let remaining = available.max(0.0);
+ let remaining = match axis {
+ Axis::Horizontal => match width {
+ Length::Shrink => 0.0,
+ _ => available.max(0.0),
+ },
+ Axis::Vertical => match height {
+ Length::Shrink => 0.0,
+ _ => available.max(0.0),
+ },
+ };
for (i, (child, tree)) in items.iter().zip(trees).enumerate() {
- let fill_factor = match axis {
- Axis::Horizontal => child.as_widget().width(),
- Axis::Vertical => child.as_widget().height(),
- }
- .fill_factor();
+ let (fill_main_factor, fill_cross_factor) = {
+ let size = child.as_widget().size();
+
+ axis.pack(size.width.fill_factor(), size.height.fill_factor())
+ };
+
+ if fill_main_factor != 0 {
+ let max_main =
+ remaining * fill_main_factor as f32 / fill_main_sum as f32;
- if fill_factor != 0 {
- let max_main = remaining * fill_factor as f32 / fill_sum as f32;
let min_main = if max_main.is_infinite() {
0.0
} else {
max_main
};
- let (min_width, min_height) =
- axis.pack(min_main, axis.cross(limits.min()));
+ let max_cross = if fill_cross_factor == 0 {
+ max_cross
+ } else {
+ cross
+ };
+ let (min_width, min_height) = axis.pack(min_main, 0.0);
let (max_width, max_height) = axis.pack(max_main, max_cross);
let child_limits = Limits::new(
@@ -154,18 +207,18 @@ where
let (x, y) = axis.pack(main, pad.1);
- node.move_to(Point::new(x, y));
+ node.move_to_mut(Point::new(x, y));
match axis {
Axis::Horizontal => {
- node.align(
+ node.align_mut(
Alignment::Start,
align_items,
Size::new(0.0, cross),
);
}
Axis::Vertical => {
- node.align(
+ node.align_mut(
align_items,
Alignment::Start,
Size::new(cross, 0.0),
@@ -178,8 +231,12 @@ where
main += axis.main(size);
}
- let (width, height) = axis.pack(main - pad.0, cross);
- let size = limits.resolve(Size::new(width, height));
+ let (intrinsic_width, intrinsic_height) = axis.pack(main - pad.0, cross);
+ let size = limits.resolve(
+ width,
+ height,
+ Size::new(intrinsic_width, intrinsic_height),
+ );
- Node::with_children(size.pad(padding), nodes)
+ Node::with_children(size.expand(padding), nodes)
}
diff --git a/core/src/layout/limits.rs b/core/src/layout/limits.rs
index 39a3d98b..7fbc7b9d 100644
--- a/core/src/layout/limits.rs
+++ b/core/src/layout/limits.rs
@@ -1,12 +1,11 @@
#![allow(clippy::manual_clamp)]
-use crate::{Length, Padding, Size};
+use crate::{Length, Size};
/// A set of size constraints for layouting.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Limits {
min: Size,
max: Size,
- fill: Size,
}
impl Limits {
@@ -14,16 +13,11 @@ impl Limits {
pub const NONE: Limits = Limits {
min: Size::ZERO,
max: Size::INFINITY,
- fill: Size::INFINITY,
};
/// Creates new [`Limits`] with the given minimum and maximum [`Size`].
pub const fn new(min: Size, max: Size) -> Limits {
- Limits {
- min,
- max,
- fill: Size::INFINITY,
- }
+ Limits { min, max }
}
/// Returns the minimum [`Size`] of the [`Limits`].
@@ -36,26 +30,15 @@ impl Limits {
self.max
}
- /// Returns the fill [`Size`] of the [`Limits`].
- pub fn fill(&self) -> Size {
- self.fill
- }
-
/// Applies a width constraint to the current [`Limits`].
pub fn width(mut self, width: impl Into<Length>) -> Limits {
match width.into() {
- Length::Shrink => {
- self.fill.width = self.min.width;
- }
- Length::Fill | Length::FillPortion(_) => {
- self.fill.width = self.fill.width.min(self.max.width);
- }
+ Length::Shrink | Length::Fill | Length::FillPortion(_) => {}
Length::Fixed(amount) => {
let new_width = amount.min(self.max.width).max(self.min.width);
self.min.width = new_width;
self.max.width = new_width;
- self.fill.width = new_width;
}
}
@@ -65,19 +48,13 @@ impl Limits {
/// Applies a height constraint to the current [`Limits`].
pub fn height(mut self, height: impl Into<Length>) -> Limits {
match height.into() {
- Length::Shrink => {
- self.fill.height = self.min.height;
- }
- Length::Fill | Length::FillPortion(_) => {
- self.fill.height = self.fill.height.min(self.max.height);
- }
+ Length::Shrink | Length::Fill | Length::FillPortion(_) => {}
Length::Fixed(amount) => {
let new_height =
amount.min(self.max.height).max(self.min.height);
self.min.height = new_height;
self.max.height = new_height;
- self.fill.height = new_height;
}
}
@@ -112,13 +89,10 @@ impl Limits {
self
}
- /// Shrinks the current [`Limits`] to account for the given padding.
- pub fn pad(&self, padding: Padding) -> Limits {
- self.shrink(Size::new(padding.horizontal(), padding.vertical()))
- }
-
/// Shrinks the current [`Limits`] by the given [`Size`].
- pub fn shrink(&self, size: Size) -> Limits {
+ pub fn shrink(&self, size: impl Into<Size>) -> Limits {
+ let size = size.into();
+
let min = Size::new(
(self.min().width - size.width).max(0.0),
(self.min().height - size.height).max(0.0),
@@ -129,12 +103,7 @@ impl Limits {
(self.max().height - size.height).max(0.0),
);
- let fill = Size::new(
- (self.fill.width - size.width).max(0.0),
- (self.fill.height - size.height).max(0.0),
- );
-
- Limits { min, max, fill }
+ Limits { min, max }
}
/// Removes the minimum width constraint for the current [`Limits`].
@@ -142,22 +111,39 @@ impl Limits {
Limits {
min: Size::ZERO,
max: self.max,
- fill: self.fill,
}
}
- /// Computes the resulting [`Size`] that fits the [`Limits`] given the
- /// intrinsic size of some content.
- pub fn resolve(&self, intrinsic_size: Size) -> Size {
- Size::new(
- intrinsic_size
- .width
- .min(self.max.width)
- .max(self.fill.width),
- intrinsic_size
+ /// Computes the resulting [`Size`] that fits the [`Limits`] given
+ /// some width and height requirements and the intrinsic size of
+ /// some content.
+ pub fn resolve(
+ &self,
+ width: impl Into<Length>,
+ height: impl Into<Length>,
+ intrinsic_size: Size,
+ ) -> Size {
+ let width = match width.into() {
+ Length::Fill | Length::FillPortion(_) => self.max.width,
+ Length::Fixed(amount) => {
+ amount.min(self.max.width).max(self.min.width)
+ }
+ Length::Shrink => {
+ intrinsic_size.width.min(self.max.width).max(self.min.width)
+ }
+ };
+
+ let height = match height.into() {
+ Length::Fill | Length::FillPortion(_) => self.max.height,
+ Length::Fixed(amount) => {
+ amount.min(self.max.height).max(self.min.height)
+ }
+ Length::Shrink => intrinsic_size
.height
.min(self.max.height)
- .max(self.fill.height),
- )
+ .max(self.min.height),
+ };
+
+ Size::new(width, height)
}
}
diff --git a/core/src/layout/node.rs b/core/src/layout/node.rs
index 2b44a7d5..5743a9bd 100644
--- a/core/src/layout/node.rs
+++ b/core/src/layout/node.rs
@@ -1,4 +1,4 @@
-use crate::{Alignment, Point, Rectangle, Size, Vector};
+use crate::{Alignment, Padding, Point, Rectangle, Size, Vector};
/// The bounds of an element and its children.
#[derive(Debug, Clone, Default)]
@@ -26,6 +26,14 @@ impl Node {
}
}
+ /// Creates a new [`Node`] that wraps a single child with some [`Padding`].
+ pub fn container(child: Self, padding: Padding) -> Self {
+ Self::with_children(
+ child.bounds.size().expand(padding),
+ vec![child.move_to(Point::new(padding.left, padding.top))],
+ )
+ }
+
/// Returns the [`Size`] of the [`Node`].
pub fn size(&self) -> Size {
Size::new(self.bounds.width, self.bounds.height)
@@ -43,6 +51,17 @@ impl Node {
/// Aligns the [`Node`] in the given space.
pub fn align(
+ mut self,
+ horizontal_alignment: Alignment,
+ vertical_alignment: Alignment,
+ space: Size,
+ ) -> Self {
+ self.align_mut(horizontal_alignment, vertical_alignment, space);
+ self
+ }
+
+ /// Mutable reference version of [`Self::align`].
+ pub fn align_mut(
&mut self,
horizontal_alignment: Alignment,
vertical_alignment: Alignment,
@@ -70,13 +89,23 @@ impl Node {
}
/// Moves the [`Node`] to the given position.
- pub fn move_to(&mut self, position: Point) {
+ pub fn move_to(mut self, position: impl Into<Point>) -> Self {
+ self.move_to_mut(position);
+ self
+ }
+
+ /// Mutable reference version of [`Self::move_to`].
+ pub fn move_to_mut(&mut self, position: impl Into<Point>) {
+ let position = position.into();
+
self.bounds.x = position.x;
self.bounds.y = position.y;
}
/// Translates the [`Node`] by the given translation.
- pub fn translate(self, translation: Vector) -> Self {
+ pub fn translate(self, translation: impl Into<Vector>) -> Self {
+ let translation = translation.into();
+
Self {
bounds: self.bounds + translation,
..self
diff --git a/core/src/length.rs b/core/src/length.rs
index 3adb996e..4c139895 100644
--- a/core/src/length.rs
+++ b/core/src/length.rs
@@ -36,6 +36,24 @@ impl Length {
Length::Fixed(_) => 0,
}
}
+
+ /// Returns `true` iff the [`Length`] is either [`Length::Fill`] or
+ // [`Length::FillPortion`].
+ pub fn is_fill(&self) -> bool {
+ self.fill_factor() != 0
+ }
+
+ /// Returns the "fluid" variant of the [`Length`].
+ ///
+ /// Specifically:
+ /// - [`Length::Shrink`] if [`Length::Shrink`] or [`Length::Fixed`].
+ /// - [`Length::Fill`] otherwise.
+ pub fn fluid(&self) -> Length {
+ match self {
+ Length::Fill | Length::FillPortion(_) => Length::Fill,
+ Length::Shrink | Length::Fixed(_) => Length::Shrink,
+ }
+ }
}
impl From<Pixels> for Length {
diff --git a/core/src/lib.rs b/core/src/lib.rs
index 54ea5839..864df6e6 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -75,3 +75,5 @@ pub use size::Size;
pub use text::Text;
pub use vector::Vector;
pub use widget::Widget;
+
+pub use smol_str::SmolStr;
diff --git a/core/src/mouse/button.rs b/core/src/mouse/button.rs
index 3eec7f42..a8f90329 100644
--- a/core/src/mouse/button.rs
+++ b/core/src/mouse/button.rs
@@ -10,6 +10,12 @@ pub enum Button {
/// The middle (wheel) button.
Middle,
+ /// The back mouse button.
+ Back,
+
+ /// The forward mouse button.
+ Forward,
+
/// Some other button.
Other(u16),
}
diff --git a/core/src/padding.rs b/core/src/padding.rs
index 0b1bba13..a63f6e29 100644
--- a/core/src/padding.rs
+++ b/core/src/padding.rs
@@ -154,3 +154,9 @@ impl From<[f32; 4]> for Padding {
}
}
}
+
+impl From<Padding> for Size {
+ fn from(padding: Padding) -> Self {
+ Self::new(padding.horizontal(), padding.vertical())
+ }
+}
diff --git a/core/src/point.rs b/core/src/point.rs
index ef42852f..cea57518 100644
--- a/core/src/point.rs
+++ b/core/src/point.rs
@@ -36,20 +36,26 @@ impl<T: Num> Point<T> {
}
}
-impl From<[f32; 2]> for Point {
- fn from([x, y]: [f32; 2]) -> Self {
+impl<T> From<[T; 2]> for Point<T>
+where
+ T: Num,
+{
+ fn from([x, y]: [T; 2]) -> Self {
Point { x, y }
}
}
-impl From<[u16; 2]> for Point<u16> {
- fn from([x, y]: [u16; 2]) -> Self {
- Point::new(x, y)
+impl<T> From<(T, T)> for Point<T>
+where
+ T: Num,
+{
+ fn from((x, y): (T, T)) -> Self {
+ Self { x, y }
}
}
-impl From<Point> for [f32; 2] {
- fn from(point: Point) -> [f32; 2] {
+impl<T> From<Point<T>> for [T; 2] {
+ fn from(point: Point<T>) -> [T; 2] {
[point.x, point.y]
}
}
diff --git a/core/src/size.rs b/core/src/size.rs
index 7ef2f602..90e50d13 100644
--- a/core/src/size.rs
+++ b/core/src/size.rs
@@ -1,4 +1,4 @@
-use crate::{Padding, Vector};
+use crate::Vector;
/// An amount of space in 2 dimensions.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -26,15 +26,7 @@ impl Size {
/// A [`Size`] with infinite width and height.
pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY);
- /// Increments the [`Size`] to account for the given padding.
- pub fn pad(&self, padding: Padding) -> Self {
- Size {
- width: self.width + padding.horizontal(),
- height: self.height + padding.vertical(),
- }
- }
-
- /// Returns the minimum of each component of this size and another
+ /// Returns the minimum of each component of this size and another.
pub fn min(self, other: Self) -> Self {
Size {
width: self.width.min(other.width),
@@ -42,13 +34,23 @@ impl Size {
}
}
- /// Returns the maximum of each component of this size and another
+ /// Returns the maximum of each component of this size and another.
pub fn max(self, other: Self) -> Self {
Size {
width: self.width.max(other.width),
height: self.height.max(other.height),
}
}
+
+ /// Expands this [`Size`] by the given amount.
+ pub fn expand(self, other: impl Into<Size>) -> Self {
+ let other = other.into();
+
+ Size {
+ width: self.width + other.width,
+ height: self.height + other.height,
+ }
+ }
}
impl From<[f32; 2]> for Size {
diff --git a/core/src/time.rs b/core/src/time.rs
index 9355ae6d..dcfe4e41 100644
--- a/core/src/time.rs
+++ b/core/src/time.rs
@@ -1,13 +1,4 @@
//! Keep track of time, both in native and web platforms!
-#[cfg(target_arch = "wasm32")]
-pub use instant::Instant;
-
-#[cfg(target_arch = "wasm32")]
-pub use instant::Duration;
-
-#[cfg(not(target_arch = "wasm32"))]
-pub use std::time::Instant;
-
-#[cfg(not(target_arch = "wasm32"))]
-pub use std::time::Duration;
+pub use web_time::Duration;
+pub use web_time::Instant;
diff --git a/core/src/widget.rs b/core/src/widget.rs
index 294d5984..7f5632ae 100644
--- a/core/src/widget.rs
+++ b/core/src/widget.rs
@@ -15,7 +15,7 @@ use crate::layout::{self, Layout};
use crate::mouse;
use crate::overlay;
use crate::renderer;
-use crate::{Clipboard, Length, Rectangle, Shell};
+use crate::{Clipboard, Length, Rectangle, Shell, Size};
/// A component that displays information and allows interaction.
///
@@ -43,11 +43,16 @@ pub trait Widget<Message, Renderer>
where
Renderer: crate::Renderer,
{
- /// Returns the width of the [`Widget`].
- fn width(&self) -> Length;
+ /// Returns the [`Size`] of the [`Widget`] in lengths.
+ fn size(&self) -> Size<Length>;
- /// Returns the height of the [`Widget`].
- fn height(&self) -> Length;
+ /// Returns a [`Size`] hint for laying out the [`Widget`].
+ ///
+ /// This hint may be used by some widget containers to adjust their sizing strategy
+ /// during construction.
+ fn size_hint(&self) -> Size<Length> {
+ self.size()
+ }
/// Returns the [`layout::Node`] of the [`Widget`].
///
diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs
index e020b030..4cabc7ce 100644
--- a/core/src/widget/text.rs
+++ b/core/src/widget/text.rs
@@ -5,7 +5,9 @@ use crate::mouse;
use crate::renderer;
use crate::text::{self, Paragraph};
use crate::widget::tree::{self, Tree};
-use crate::{Color, Element, Layout, Length, Pixels, Point, Rectangle, Widget};
+use crate::{
+ Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget,
+};
use std::borrow::Cow;
@@ -134,12 +136,11 @@ where
tree::State::new(State(Renderer::Paragraph::default()))
}
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- self.height
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: self.height,
+ }
}
fn layout(
@@ -205,28 +206,27 @@ pub fn layout<Renderer>(
where
Renderer: text::Renderer,
{
- let limits = limits.width(width).height(height);
- let bounds = limits.max();
-
- let size = size.unwrap_or_else(|| renderer.default_size());
- let font = font.unwrap_or_else(|| renderer.default_font());
-
- let State(ref mut paragraph) = state;
-
- paragraph.update(text::Text {
- content,
- bounds,
- size,
- line_height,
- font,
- horizontal_alignment,
- vertical_alignment,
- shaping,
- });
-
- let size = limits.resolve(paragraph.min_bounds());
-
- layout::Node::new(size)
+ layout::sized(limits, width, height, |limits| {
+ let bounds = limits.max();
+
+ let size = size.unwrap_or_else(|| renderer.default_size());
+ let font = font.unwrap_or_else(|| renderer.default_font());
+
+ let State(ref mut paragraph) = state;
+
+ paragraph.update(text::Text {
+ content,
+ bounds,
+ size,
+ line_height,
+ font,
+ horizontal_alignment,
+ vertical_alignment,
+ shaping,
+ });
+
+ paragraph.min_bounds()
+ })
}
/// Draws text using the same logic as the [`Text`] widget.
diff --git a/core/src/window/event.rs b/core/src/window/event.rs
index b9ee7aca..a14d127f 100644
--- a/core/src/window/event.rs
+++ b/core/src/window/event.rs
@@ -58,7 +58,7 @@ pub enum Event {
/// for each file separately.
FileHovered(PathBuf),
- /// A file has beend dropped into the window.
+ /// A file has been dropped into the window.
///
/// When the user drops multiple files at once, this event will be emitted
/// for each file separately.