Add RustColors singleton helper.

This commit is contained in:
Shaun Reed 2025-03-30 11:20:21 -04:00
parent be9981291c
commit d2f5823594
11 changed files with 145 additions and 197 deletions

View File

@ -10,7 +10,8 @@ fn main() {
.qt_module("Network") .qt_module("Network")
.qml_module(QmlModule { .qml_module(QmlModule {
uri: "clide.module", uri: "clide.module",
rust_files: &["src/line_count.rs"], rust_files: &["src/line_count.rs",
"src/colors.rs"],
qml_files: &["qml/main.qml", qml_files: &["qml/main.qml",
"qml/ProjectView/ClideProjectView.qml", "qml/ProjectView/ClideProjectView.qml",
"qml/Editor/ClideEditor.qml", "qml/Editor/ClideEditor.qml",

View File

@ -11,14 +11,15 @@ SplitView {
// Customized handle to drag between the Editor and the Console. // Customized handle to drag between the Editor and the Console.
handle: Rectangle { handle: Rectangle {
border.color: SplitHandle.hovered ? "#2b2b2b" : "#3c3f41" border.color: SplitHandle.pressed ? RustColors.pressed : SplitHandle.hovered ? RustColors.hovered : RustColors.gutter
color: SplitHandle.pressed ? "#4b4f51" : "#3c3f41" color: SplitHandle.pressed ? RustColors.pressed : SplitHandle.hovered ? RustColors.hovered : RustColors.gutter
implicitHeight: 8 implicitHeight: 8
opacity: SplitHandle.hovered || areaConsole.height < 15 ? 1.0 : 0.0 radius: 2.5
Behavior on opacity { // Execute these behaviors when the color is changed.
OpacityAnimator { Behavior on color {
duration: 700 ColorAnimation {
duration: 400
} }
} }
} }
@ -33,7 +34,7 @@ SplitView {
Layout.fillWidth: false Layout.fillWidth: false
// Calculate the width based on the logarithmic scale. // Calculate the width based on the logarithmic scale.
Layout.preferredWidth: fontMetrics.averageCharacterWidth * (Math.floor(Math.log10(areaText.lineCount)) + 1) + 10 Layout.preferredWidth: fontMetrics.averageCharacterWidth * (Math.floor(Math.log10(textArea.lineCount)) + 1) + 10
contentY: editorFlickable.contentY contentY: editorFlickable.contentY
interactive: false interactive: false
visible: true visible: true
@ -49,14 +50,15 @@ SplitView {
delegate: Item { delegate: Item {
required property int index required property int index
height: 17 // Calculate the height of each line in the text area.
height: textArea.contentHeight / textArea.lineCount
width: parent.width width: parent.width
Label { Label {
id: numbers id: numbers
color: "white" color: "white"
font: areaText.font font: textArea.font
height: parent.height height: parent.height
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
text: parent.index + 1 text: parent.index + 1
@ -67,20 +69,19 @@ SplitView {
id: indicator id: indicator
anchors.left: numbers.right anchors.left: numbers.right
color: Qt.darker("#FFF", 3) color: RustColors.linenumber
height: parent.height height: parent.height
width: 1 width: 1
} }
} }
model: areaText.lineCount // TODO: Bug where text wrapping shows as new line number.
model: textArea.lineCount
} }
} }
} }
Flickable { Flickable {
id: editorFlickable id: editorFlickable
property alias areaText: areaText
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
@ -91,20 +92,19 @@ SplitView {
ScrollBar.vertical: MyScrollBar { ScrollBar.vertical: MyScrollBar {
} }
TextArea.flickable: TextArea { TextArea.flickable: TextArea {
id: areaText id: textArea
color: RustColors.editor_text
color: "#ccced3"
focus: true focus: true
persistentSelection: true persistentSelection: true
selectByMouse: true selectByMouse: true
// selectedTextColor: control.palette.highlightedText // selectedTextColor: RustColors.editor_highlighted_text
// selectionColor: control.palette.highlight // selectionColor: RustColors.editor_highlight
textFormat: Qt.AutoText textFormat: Qt.AutoText
wrapMode: TextArea.Wrap wrapMode: TextArea.Wrap
background: Rectangle { background: Rectangle {
color: "#2b2b2b" color: RustColors.editor_background
} }
onLinkActivated: function (link) { onLinkActivated: function (link) {
@ -137,7 +137,7 @@ SplitView {
FontMetrics { FontMetrics {
id: fontMetrics id: fontMetrics
font: areaText.font font: textArea.font
} }
} }
} }
@ -150,9 +150,9 @@ SplitView {
readOnly: true readOnly: true
wrapMode: TextArea.Wrap wrapMode: TextArea.Wrap
background: Rectangle { background: Rectangle {
color: "#2b2b2b" color: RustColors.editor_background
implicitHeight: 100 implicitHeight: 100
// border.color: control.enabled ? "#21be2b" : "transparent" // border.color: control.enabled ? RustColors.active : RustColors.inactive
} }
} }
@ -163,11 +163,12 @@ SplitView {
// Scroll bar gutter // Scroll bar gutter
background: Rectangle { background: Rectangle {
color: "#3b3b3b"
implicitHeight: scrollBar.interactive ? 8 : 4 implicitHeight: scrollBar.interactive ? 8 : 4
implicitWidth: scrollBar.interactive ? 8 : 4 implicitWidth: scrollBar.interactive ? 8 : 4
opacity: scrollBar.active && scrollBar.size < 1.0 ? 1.0 : 0.0 color: RustColors.scrollbar_gutter
// Fade the scrollbar gutter when inactive.
opacity: scrollBar.active && scrollBar.size < 1.0 ? 1.0 : 0.2
Behavior on opacity { Behavior on opacity {
OpacityAnimator { OpacityAnimator {
duration: 500 duration: 500
@ -177,16 +178,25 @@ SplitView {
// Scroll bar // Scroll bar
contentItem: Rectangle { contentItem: Rectangle {
color: "#4b4f51"
implicitHeight: scrollBar.interactive ? 8 : 4 implicitHeight: scrollBar.interactive ? 8 : 4
implicitWidth: scrollBar.interactive ? 8 : 4 implicitWidth: scrollBar.interactive ? 8 : 4
opacity: scrollBar.active && scrollBar.size < 1.0 ? 1.0 : 0.2
Behavior on opacity { // If we don't need a scrollbar, fallback to the gutter color.
OpacityAnimator { // If the scrollbar is required change it's color based on activity.
color: scrollBar.size < 1.0 ? scrollBar.active ? RustColors.scrollbar_active : RustColors.scrollbar : RustColors.scrollbar_gutter
// Smooth transition between color changes based on the state above.
Behavior on color {
ColorAnimation {
duration: 1000 duration: 1000
} }
} }
// Fade the scrollbar when inactive.
opacity: scrollBar.active && scrollBar.size < 1.0 ? 1.0 : 0.35
Behavior on opacity {
OpacityAnimator {
duration: 500
}
}
} }
} }
} }

View File

@ -1,9 +1,11 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import clide.module 1.0
Menu { Menu {
background: Rectangle { background: Rectangle {
color: "#3c3f41" color: RustColors.menubar
implicitWidth: 100 implicitWidth: 100
radius: 2 radius: 2
} }

View File

@ -1,10 +1,12 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import clide.module 1.0
MenuBar { MenuBar {
background: Rectangle { background: Rectangle {
color: "#3c3f41" color: RustColors.menubar
border.color: "#575757" border.color: RustColors.menubar_border
} }
Action { Action {
@ -44,7 +46,7 @@ MenuBar {
MenuSeparator { MenuSeparator {
background: Rectangle { background: Rectangle {
border.color: color border.color: color
color: "#3c3f41" color: RustColors.menubar_border
implicitHeight: 3 implicitHeight: 3
implicitWidth: 200 implicitWidth: 200
} }

View File

@ -1,140 +0,0 @@
import QtQuick
import QtQuick.Controls
MenuBar {
background: Rectangle {
color: "#3c3f41"
border.color: "#575757"
}
Action {
id: actionNewProject
text: qsTr("&New Project...")
}
Action {
id: actionOpen
text: qsTr("&Open...")
}
Action {
id: actionSave
text: qsTr("&Save")
}
Action {
id: actionExit
text: qsTr("&Exit")
onTriggered: Qt.quit()
}
ClideMenu {
title: qsTr("&File")
ClideMenuBarItem {
action: actionNewProject
}
ClideMenuBarItem {
action: actionOpen
}
ClideMenuBarItem {
action: actionSave
}
MenuSeparator {
background: Rectangle {
border.color: color
color: "#3c3f41"
implicitHeight: 3
implicitWidth: 200
}
}
ClideMenuBarItem {
action: actionExit
}
}
Action {
id: actionUndo
text: qsTr("&Undo")
}
Action {
id: actionRedo
text: qsTr("&Redo")
}
Action {
id: actionCut
text: qsTr("&Cut")
}
Action {
id: actionCopy
text: qsTr("&Copy")
}
Action {
id: actionPaste
text: qsTr("&Paste")
}
ClideMenu {
title: qsTr("&Edit")
ClideMenuBarItem {
action: actionUndo
}
ClideMenuBarItem {
action: actionRedo
}
ClideMenuBarItem {
action: actionCut
}
ClideMenuBarItem {
action: actionCopy
}
ClideMenuBarItem {
action: actionPaste
}
}
Action {
id: actionToolWindows
text: qsTr("&Tool Windows")
}
Action {
id: actionAppearance
text: qsTr("&Appearance")
}
ClideMenu {
title: qsTr("&View")
ClideMenuBarItem {
action: actionToolWindows
}
ClideMenuBarItem {
action: actionAppearance
}
}
Action {
id: actionDocumentation
text: qsTr("&Documentation")
}
Action {
id: actionAbout
text: qsTr("&About")
}
ClideMenu {
title: qsTr("&Help")
ClideMenuBarItem {
action: actionDocumentation
}
ClideMenuBarItem {
action: actionAbout
}
}
}

View File

@ -1,11 +1,13 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import clide.module 1.0
MenuItem { MenuItem {
id: root id: root
background: Rectangle { background: Rectangle {
color: root.hovered ? "#4b4f51" : "#3c3f41" // Hover effect color: root.hovered ? RustColors.hovered : RustColors.unhovered
radius: 2.5 radius: 2.5
} }
contentItem: IconLabel { contentItem: IconLabel {

View File

@ -1,16 +0,0 @@
import QtQuick
import QtQuick.Controls
MenuItem {
id: root
background: Rectangle {
color: root.hovered ? "#4b4f51" : "#3c3f41" // Hover effect
radius: 2.5
}
contentItem: IconLabel {
color: "black"
font.family: "Helvetica"
text: root.text
}
}

View File

@ -4,6 +4,8 @@ import QtQuick.Layouts
import "../Editor" import "../Editor"
import clide.module 1.0
SplitView { SplitView {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
@ -11,14 +13,15 @@ SplitView {
// Customized handle to drag between the Navigation and the Editor. // Customized handle to drag between the Navigation and the Editor.
handle: Rectangle { handle: Rectangle {
border.color: SplitHandle.hovered ? "#303234" : "#3c3f41" border.color: SplitHandle.pressed ? RustColors.pressed : SplitHandle.hovered ? RustColors.hovered : RustColors.gutter
color: SplitHandle.pressed ? "#4b4f51" : "#3c3f41" color: SplitHandle.pressed ? RustColors.pressed : SplitHandle.hovered ? RustColors.hovered : RustColors.gutter
implicitWidth: 8 implicitWidth: 8
opacity: SplitHandle.hovered || navigationView.width < 15 ? 1.0 : 0.0 radius: 2.5
Behavior on opacity { // Execute these behaviors when the color is changed.
OpacityAnimator { Behavior on color {
duration: 700 ColorAnimation {
duration: 400
} }
} }
} }
@ -28,7 +31,7 @@ SplitView {
SplitView.fillHeight: true SplitView.fillHeight: true
SplitView.preferredWidth: 200 SplitView.preferredWidth: 200
color: "#303234" color: RustColors.explorer_background
StackLayout { StackLayout {
anchors.fill: parent anchors.fill: parent

View File

@ -21,8 +21,9 @@ ApplicationWindow {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: "#1e1f22" color: RustColors.gutter
} }
MessageDialog { MessageDialog {
id: errorDialog id: errorDialog

77
src/colors.rs Normal file
View File

@ -0,0 +1,77 @@
#[cxx_qt::bridge]
pub mod qobject {
unsafe extern "C++" {
include!("cxx-qt-lib/qcolor.h");
type QColor = cxx_qt_lib::QColor;
}
unsafe extern "RustQt" {
#[qobject]
#[qml_element]
#[qml_singleton]
#[qproperty(QColor, hovered)]
#[qproperty(QColor, unhovered)]
#[qproperty(QColor, pressed)]
#[qproperty(QColor, menubar)]
#[qproperty(QColor, menubar_border)]
#[qproperty(QColor, scrollbar)]
#[qproperty(QColor, scrollbar_active)]
#[qproperty(QColor, scrollbar_gutter)]
#[qproperty(QColor, linenumber)]
#[qproperty(QColor, active)]
#[qproperty(QColor, inactive)]
#[qproperty(QColor, editor_background)]
#[qproperty(QColor, editor_text)]
#[qproperty(QColor, editor_highlighted_text)]
#[qproperty(QColor, editor_highlight)]
#[qproperty(QColor, gutter)]
#[qproperty(QColor, explorer_background)]
type RustColors = super::RustColorsImpl;
}
}
use cxx_qt_lib::QColor;
pub struct RustColorsImpl {
hovered: QColor,
unhovered: QColor,
pressed: QColor,
menubar: QColor,
menubar_border: QColor,
scrollbar: QColor,
scrollbar_active: QColor,
scrollbar_gutter: QColor,
linenumber: QColor,
active: QColor,
inactive: QColor,
editor_background: QColor,
editor_text: QColor,
editor_highlighted_text: QColor,
editor_highlight: QColor,
gutter: QColor,
explorer_background: QColor,
}
impl Default for RustColorsImpl {
fn default() -> Self {
Self {
hovered: QColor::try_from("#303234").unwrap(),
unhovered: QColor::try_from("#3c3f41").unwrap(),
pressed: QColor::try_from("#4b4f51").unwrap(),
menubar: QColor::try_from("#3c3f41").unwrap(),
menubar_border: QColor::try_from("#575757").unwrap(),
scrollbar: QColor::try_from("#4b4f51").unwrap(),
scrollbar_active: QColor::try_from("#4b4f51").unwrap(),
scrollbar_gutter: QColor::try_from("#3b3b3b").unwrap(),
linenumber: QColor::try_from("#FFF").unwrap(),
active: QColor::try_from("#a9acb0").unwrap(),
inactive: QColor::try_from("#FFF").unwrap(),
editor_background: QColor::try_from("#2b2b2b").unwrap(),
editor_text: QColor::try_from("#ccced3").unwrap(),
editor_highlighted_text: QColor::try_from("#ccced3").unwrap(),
editor_highlight: QColor::try_from("#ccced3").unwrap(),
gutter: QColor::try_from("#1e1f22").unwrap(),
explorer_background: QColor::try_from("#3c3f41").unwrap(),
}
}
}

View File

@ -1,6 +1,9 @@
// TODO: Header // TODO: Header
use cxx_qt_lib::QString;
pub mod line_count; pub mod line_count;
pub mod colors;
fn main() { fn main() {
use cxx_qt_lib::{QGuiApplication, QQmlApplicationEngine, QUrl}; use cxx_qt_lib::{QGuiApplication, QQmlApplicationEngine, QUrl};
@ -8,6 +11,9 @@ fn main() {
let mut app = QGuiApplication::new(); let mut app = QGuiApplication::new();
let mut engine = QQmlApplicationEngine::new(); let mut engine = QQmlApplicationEngine::new();
if let Some(engine) = engine.as_mut() {
engine.add_import_path(&QString::from("qml/"));
}
if let Some(engine) = engine.as_mut() { if let Some(engine) = engine.as_mut() {
engine.load(&QUrl::from("qml/main.qml")); engine.load(&QUrl::from("qml/main.qml"));
} }