diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..e9c7deae --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.16) +project(FluentUI VERSION 0.1 LANGUAGES CXX) +add_subdirectory(src) +add_subdirectory(example) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 00000000..d41ac6df --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.16) +project(example) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +set(CMAKE_CXX_STANDARD 17) + +find_package(Qt6 COMPONENTS Core Quick QuickControls2 Concurrent Network Multimedia REQUIRED) + +set(SOURCES + ChatController.cpp + main.cpp +) + +set(HEADERS + ChatController.h +) + +set(RESOURCES + qml.qrc +) + +set(RC_ICONS + favicon.ico +) + +qt_add_resources(QT_RESOURCES ${RESOURCES}) + +if(WIN32) + if(QT_ARCH EQUAL 32) + set(COPYDLL ${CMAKE_CURRENT_SOURCE_DIR}/../third/Win_x86/*.dll ${DESTDIR}) + else() + set(COPYDLL ${CMAKE_CURRENT_SOURCE_DIR}/../third/Win_x64/*.dll ${DESTDIR}) + endif() + if(QMAKE_CC STREQUAL "cl") + set(QMAKE_PRE_LINK "${QMAKE_COPY} ${COPYDLL}") + else() + set(QMAKE_PRE_LINK "${QMAKE_COPY} ${COPYDLL}") + endif() +endif() + +add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS} ${QT_RESOURCES} ${RC_ICONS}) + +target_compile_definitions(${PROJECT_NAME} PRIVATE + QT_DEPRECATED_WARNINGS + QT_NO_WARNING_OUTPUT +) + +target_link_libraries(${PROJECT_NAME} PRIVATE + Qt6::Core + Qt6::Quick + Qt6::QuickControls2 + Qt6::Concurrent + Qt6::Network + Qt6::Multimedia +) + +if(WIN32) + target_compile_definitions(${PROJECT_NAME} PRIVATE UNICODE WIN32 _WINDOWS) + target_link_libraries(${PROJECT_NAME} PRIVATE dwmapi user32) +endif() + +if(APPLE) + set_target_properties(${PROJECT_NAME} PROPERTIES + MACOSX_BUNDLE_INFO_PLIST Info.plist + ) +endif() diff --git a/example/T_Home.qml b/example/T_Home.qml index 3325822b..af0cd729 100644 --- a/example/T_Home.qml +++ b/example/T_Home.qml @@ -129,7 +129,7 @@ FluScrollablePage{ id:item_mouse anchors.fill: parent hoverEnabled: true - onWheel: { + onWheel: (wheel)=>{ if (wheel.angleDelta.y > 0) scrollbar_header.decrease() else scrollbar_header.increase() } diff --git a/example/T_TextBox.qml b/example/T_TextBox.qml index 278d672b..e9606d53 100644 --- a/example/T_TextBox.qml +++ b/example/T_TextBox.qml @@ -17,7 +17,7 @@ FluScrollablePage{ Layout.preferredWidth: 300 disabled:toggle_switch.selected } - FluMultiLineTextBox{ + FluMultilineTextBox{ Layout.topMargin: 20 Layout.preferredWidth: 300 placeholderText: "多行输入框" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..201b8ba0 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 3.16) +project(FluentUI) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +find_package(Qt6 COMPONENTS Core Quick Svg REQUIRED) +set(QT_INSTALL_QML ${Qt6Core_DIR}/../../../qml) +set(TARGET_TYPE SHARED) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/FluentUI) +set(TARGET_RESOURCES res.qrc) +set(TARGET_SOURCES + Def.cpp + FluApp.cpp + FluColorSet.cpp + FluColors.cpp + FluRegister.cpp + FluTheme.cpp + Fluent.cpp + FluentUI.cpp + WindowHelper.cpp + qml_plugin.cpp +) + +set(TARGET_HEADERS + Def.h + FluApp.h + FluColorSet.h + FluColors.h + FluRegister.h + FluTheme.h + Fluent.h + FluentUI.h + FramelessView.h + WindowHelper.h + qml_plugin.h + stdafx.h +) + +if(WIN32) + set(TARGET_SOURCES ${TARGET_SOURCES} FramelessView_win.cpp) +else() + set(TARGET_SOURCES ${TARGET_SOURCES} FramelessView_unix.cpp) +endif() + +add_library(${PROJECT_NAME} ${TARGET_TYPE} ${TARGET_SOURCES} ${TARGET_HEADERS} ${TARGET_RESOURCES}) + +target_compile_definitions(${PROJECT_NAME} PRIVATE VERSION_IN=\\\"1.0.0\\\" URI_STR=\\\"FluentUI\\\") + +if(WIN32) + target_link_libraries(${PROJECT_NAME} PRIVATE dwmapi user32) +else() +endif() + +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick Qt6::Svg) + +if(WIN32) + include(build_windows.cmake) +else() + include(build_macos.cmake) +endif() diff --git a/src/Fluent.cpp b/src/Fluent.cpp index 41aa118e..f0d8e866 100644 --- a/src/Fluent.cpp +++ b/src/Fluent.cpp @@ -22,7 +22,7 @@ Fluent *Fluent::getInstance() QString Fluent::version() const { - return QStringLiteral(VERSION_IN); + return QStringLiteral("1.0.0"); } void Fluent::registerTypes(const char *uri){ @@ -59,7 +59,7 @@ void Fluent::registerTypes(const char *uri){ qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluMenu.qml"),uri,major,minor,"FluMenu"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluScrollBar.qml"),uri,major,minor,"FluScrollBar"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTextButton.qml"),uri,major,minor,"FluTextButton"); - qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluMultiLineTextBox.qml"),uri,major,minor,"FluMultiLineTextBox"); + qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluMultilineTextBox.qml"),uri,major,minor,"FluMultilineTextBox"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTooltip.qml"),uri,major,minor,"FluTooltip"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluDivider.qml"),uri,major,minor,"FluDivider"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluIcon.qml"),uri,major,minor,"FluIcon"); diff --git a/src/build_macos.cmake b/src/build_macos.cmake new file mode 100644 index 00000000..93fe68ae --- /dev/null +++ b/src/build_macos.cmake @@ -0,0 +1,37 @@ +set(OUTP "${CMAKE_CURRENT_BINARY_DIR}/../bin/FluentUI/") + +add_definitions(-DMACOS) + +# Set DESTDIR to the output directory +set(CMAKE_INSTALL_PREFIX ${OUTP}) +set(CMAKE_INSTALL_DESTDIR ${OUTP}) + +# Add the current source directory to the include path +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +# Set MOC options +set(QMAKE_MOC_OPTIONS -Muri=${uri}) + +# Set pre-link commands +add_custom_command( + TARGET ${PROJECT_NAME} PRE_LINK + COMMAND chmod -R 777 ${CMAKE_CURRENT_SOURCE_DIR}/macos_install.sh + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/macos_install.sh PRESET ${CMAKE_CURRENT_SOURCE_DIR}/ ${OUTP} +) + +# Set post-link commands for shared library +if(BUILD_SHARED_LIBS) + # Set INST_QMLPATH variable + set(INST_QMLPATH "${QT_INSTALL_QML}/${uri}" REPLACE "\\" "/") + + # Set post-link command + add_custom_command( + TARGET ${PROJECT_NAME} POST_LINK + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/macos_install.sh INSTALL ${CMAKE_CURRENT_SOURCE_DIR}/ ${OUTP} ${INST_QMLPATH} + ) + + # Include dev.pri if it exists + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../../dev.pri) + include(${CMAKE_CURRENT_SOURCE_DIR}/../../dev.pri) + endif() +endif() diff --git a/src/build_windows.cmake b/src/build_windows.cmake new file mode 100644 index 00000000..de5ebef0 --- /dev/null +++ b/src/build_windows.cmake @@ -0,0 +1,27 @@ +set(OUTP "${CMAKE_BINARY_DIR}/src/../bin/FluentUI") +set(BUILDBIN_PATH "${OUTP}") +set(QTQMLFLUENT_PATH "${QT_INSTALL_QML}/FluentUI") +set(PRESET_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-preset") +set(SOLIBFILE_PATH "${CMAKE_BINARY_DIR}/libFluentUI.so") +set(ANDROID NO) +if (ANDROID) + set(ANDROID YES) + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTP}) +else() + set(CMAKE_INSTALL_PREFIX "${OUTP}") +endif() +set(SHAREDSCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/win_install.bat SHARED ${CMAKE_CURRENT_SOURCE_DIR} ${PRESET_PATH} ${BUILDBIN_PATH} ${QTQMLFLUENT_PATH} ${ANDROID} ${SOLIBFILE_PATH}) +set(STATICSCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/win_install.bat STATIC ${CMAKE_CURRENT_SOURCE_DIR} ${PRESET_PATH} ${BUILDBIN_PATH} ${QTQMLFLUENT_PATH} ${ANDROID} ${SOLIBFILE_PATH}) +string(REPLACE "/" "\\" SHAREDSCRIPT "${SHAREDSCRIPT}") +string(REPLACE "/" "\\" STATICSCRIPT "${STATICSCRIPT}") +if (${TARGET_TYPE} STREQUAL "SHARED") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${SHAREDSCRIPT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) +else() + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${STATICSCRIPT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) +endif() diff --git a/src/build_windows.pri b/src/build_windows.pri index ea50cb7d..c8bc7dbc 100644 --- a/src/build_windows.pri +++ b/src/build_windows.pri @@ -1,5 +1,8 @@ OUTP = $$OUT_PWD/../bin/FluentUI BUILDBIN_PATH = $$replace(OUTP, src/../bin, bin) +message("----------------->") +message($$OUTP) +message($$BUILDBIN_PATH) QTQMLFLUENT_PATH = $$[QT_INSTALL_QML]/FluentUI PRESET_PATH = $$PWD/build-preset SOLIBFILE_PATH = $$OUT_PWD/libFluentUI.so @@ -15,6 +18,8 @@ android{ SHAREDSCRIPT = "$$PWD\win_install.bat" SHARED "$$PWD" "$$PRESET_PATH" "$$BUILDBIN_PATH" "$$QTQMLFLUENT_PATH" $$ANDROID "$$SOLIBFILE_PATH" STATICSCRIPT = "$$PWD\win_install.bat" STATIC "$$PWD" "$$PRESET_PATH" "$$BUILDBIN_PATH" "$$QTQMLFLUENT_PATH" $$ANDROID "$$SOLIBFILE_PATH" +message("-------------------------") +message($$SHAREDSCRIPT) CONFIG(sharedlib){ QMAKE_POST_LINK *= $$replace(SHAREDSCRIPT, /, \\) } diff --git a/src/colorpicker/content/ColorSlider.qml b/src/colorpicker/content/ColorSlider.qml index de43acdc..bcc35355 100644 --- a/src/colorpicker/content/ColorSlider.qml +++ b/src/colorpicker/content/ColorSlider.qml @@ -30,10 +30,10 @@ Item { pickerCursor.y = Math.max(0, Math.min(height, mouse.y)-cursorHeight) } } - onPositionChanged: { + onPositionChanged:(mouse)=> { handleMouse(mouse) } - onPressed: handleMouse(mouse) + onPressed:(mouse)=> handleMouse(mouse) } function setValue(val) { diff --git a/src/controls/FluAppBar.qml b/src/controls/FluAppBar.qml index 4bdd590c..2dfb103e 100644 --- a/src/controls/FluAppBar.qml +++ b/src/controls/FluAppBar.qml @@ -7,16 +7,28 @@ import FluentUI Rectangle{ property string title: "" + property string darkText : "夜间模式" + property string minimizeText : "最小化" + property string restoreText : "向下还原" + property string maximizeText : "最大化" + property string closeText : "关闭" property color textColor: FluTheme.dark ? "#FFFFFF" : "#000000" + property color minimizeNormalColor: Qt.rgba(0,0,0,0) + property color minimizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.1) : Qt.rgba(0,0,0,0.06) + property color maximizeNormalColor: Qt.rgba(0,0,0,0) + property color maximizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.1) : Qt.rgba(0,0,0,0.06) + property color closeNormalColor: Qt.rgba(0,0,0,0) + property color closeHoverColor: Qt.rgba(251/255,115/255,115/255,1) + + property bool showDark: false - property bool showFps: false - property var window: Window.window property color borerlessColor : FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark - property bool resizable: { - if(window == null){ - return false - } - return !(window.minimumHeight === window.maximumHeight && window.maximumWidth === window.minimumWidth) + + Item{ + id:d + property var win: Window.window + property bool isRestore: win && Window.Maximized === win.visibility + property bool resizable: win && !(win.minimumHeight === win.maximumHeight && win.maximumWidth === win.minimumWidth) } id:root @@ -34,7 +46,7 @@ Rectangle{ DragHandler { target: null grabPermissions: TapHandler.CanTakeOverFromAnything - onActiveChanged: if (active) { window.startSystemMove(); } + onActiveChanged: if (active) { d.win.startSystemMove(); } } FluText { @@ -62,7 +74,7 @@ Rectangle{ visible: showDark spacing: 5 FluText{ - text:"夜间模式" + text:darkText color:root.textColor } FluToggleSwitch{ @@ -79,53 +91,24 @@ Rectangle{ iconSource : FluentIcons.ChromeMinimize Layout.alignment: Qt.AlignVCenter iconSize: 11 - text:"最小化" + text:minimizeText radius: 0 textColor: root.textColor - color:{ - if(FluTheme.dark){ - if(hovered){ - return Qt.rgba(1,1,1,0.06) - } - return Qt.rgba(0,0,0,0) - }else{ - if(hovered){ - return Qt.rgba(0,0,0,0.06) - } - return Qt.rgba(0,0,0,0) - } - } + color: hovered ? minimizeHoverColor : minimizeNormalColor onClicked: { - window.showMinimized() + d.win.showMinimized() } } FluIconButton{ width: 40 height: 30 - property bool isRestore:{ - if(window == null) - return false - return Window.Maximized === window.visibility - } - iconSource : isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize - color:{ - if(FluTheme.dark){ - if(hovered){ - return Qt.rgba(1,1,1,0.06) - } - return Qt.rgba(0,0,0,0) - }else{ - if(hovered){ - return Qt.rgba(0,0,0,0.06) - } - return Qt.rgba(0,0,0,0) - } - } + iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize + color: hovered ? maximizeHoverColor : maximizeNormalColor Layout.alignment: Qt.AlignVCenter - visible: resizable + visible: d.resizable radius: 0 textColor: root.textColor - text:isRestore?"向下还原":"最大化" + text:d.isRestore?restoreText:maximizeText iconSize: 11 onClicked: { toggleMaximized() @@ -134,26 +117,26 @@ Rectangle{ FluIconButton{ iconSource : FluentIcons.ChromeClose Layout.alignment: Qt.AlignVCenter - text:"关闭" + text:closeText width: 40 height: 30 radius: 0 iconSize: 10 textColor: hovered ? Qt.rgba(1,1,1,1) : root.textColor - color:hovered ? Qt.rgba(251/255,115/255,115/255,1) : "#00000000" + color:hovered ? closeHoverColor : closeNormalColor onClicked: { - Window.window.close() + d.win.close() } } } function toggleMaximized() { - if(!resizable) + if(!d.resizable) return - if (window.visibility === Window.Maximized) { - window.showNormal(); + if (d.win.visibility === Window.Maximized) { + d.win.showNormal(); } else { - window.showMaximized(); + d.win.showMaximized(); } } diff --git a/src/controls/FluAutoSuggestBox.qml b/src/controls/FluAutoSuggestBox.qml index 572828cb..40af7097 100644 --- a/src/controls/FluAutoSuggestBox.qml +++ b/src/controls/FluAutoSuggestBox.qml @@ -6,34 +6,40 @@ TextField{ property var items:[] property int fontStyle: FluText.Body + property string emptyText: "没有找到结果" property int pixelSize : FluTheme.textSize property int iconSource: 0 property bool disabled: false signal itemClicked(var data) signal handleClicked + property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) QtObject{ id:d property bool flagVisible: true } - id:input + id:control width: 300 enabled: !disabled color: { if(disabled){ - return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + return disableColor } - return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + return normalColor } selectionColor: FluTheme.primaryColor.lightest renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering placeholderTextColor: { if(disabled){ - return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + return placeholderDisableColor } if(focus){ - return FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + return placeholderFocusColor } - return FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + return placeholderNormalColor } rightPadding: icon_right.visible ? 50 : 30 selectByMouse: true @@ -92,27 +98,25 @@ TextField{ width: 20 height: 20 opacity: 0.5 - visible: input.text !== "" + visible: control.text !== "" anchors{ verticalCenter: parent.verticalCenter right: parent.right rightMargin: icon_right.visible ? 25 : 5 } onClicked:{ - input.text = "" + control.text = "" } } background: FluTextBoxBackground{ - inputItem: input - - + inputItem: control FluIcon{ id:icon_right - iconSource: input.iconSource + iconSource: control.iconSource iconSize: 15 opacity: 0.5 - visible: input.iconSource != 0 + visible: control.iconSource != 0 anchors{ verticalCenter: parent.verticalCenter right: parent.right @@ -122,18 +126,18 @@ TextField{ } Component.onCompleted: { - searchData() + loadData() } Popup{ - id:input_popup - y:input.height + id:control_popup + y:control.height focus: false enter: Transition { NumberAnimation { property: "y" from:0 - to:input_popup.y + to:control_popup.y duration: 150 } NumberAnimation { @@ -149,7 +153,7 @@ TextField{ } } background: Rectangle{ - width: input.width + width: control.width radius: 4 FluShadow{ radius: 4 @@ -163,11 +167,11 @@ TextField{ currentIndex: -1 ScrollBar.vertical: FluScrollBar {} header: Item{ - width: input.width + width: control.width height: visible ? 38 : 0 visible: list_view.count === 0 FluText{ - text:"没有找到结果" + text:emptyText anchors{ verticalCenter: parent.verticalCenter left: parent.left @@ -176,7 +180,7 @@ TextField{ } } delegate:Control{ - width: input.width + width: control.width padding:10 background: Rectangle{ color: { @@ -192,7 +196,7 @@ TextField{ id:mouse_area anchors.fill: parent Connections{ - target: input + target: control function onHandleClicked(){ if((list_view.currentIndex === index)){ handleClick(modelData) @@ -223,72 +227,41 @@ TextField{ } } } + onTextChanged: { + loadData() + if(d.flagVisible){ + control_popup.visible = true + } + } + TapHandler { + acceptedButtons: Qt.RightButton + onTapped: control.echoMode !== TextInput.Password && menu.popup() + } + FluTextBoxMenu{ + id:menu + inputItem: control + } function handleClick(modelData){ - input_popup.visible = false - input.itemClicked(modelData) + control_popup.visible = false + control.itemClicked(modelData) updateText(modelData.title) } function updateText(text){ d.flagVisible = false - input.text = text + control.text = text d.flagVisible = true } - onTextChanged: { - searchData() - if(d.flagVisible){ - input_popup.visible = true - } - } - - TapHandler { - acceptedButtons: Qt.RightButton - onTapped: input.echoMode !== TextInput.Password && menu.popup() - } - - FluMenu{ - id:menu - focus: false - FluMenuItem{ - text: "剪切" - visible: input.text !== "" - onClicked: { - input.cut() - } - } - FluMenuItem{ - text: "复制" - visible: input.selectedText !== "" - onClicked: { - input.copy() - } - } - FluMenuItem{ - text: "粘贴" - visible: input.canPaste - onClicked: { - input.paste() - } - } - FluMenuItem{ - text: "全选" - visible: input.text !== "" - onClicked: { - input.selectAll() - } - } - } - - function searchData(){ + function loadData(){ var result = [] if(items==null){ list_view.model = result return } items.map(function(item){ - if(item.title.indexOf(input.text)!==-1){ + if(item.title.indexOf(control.text)!==-1){ result.push(item) } }) diff --git a/src/controls/FluCalendarPicker.qml b/src/controls/FluCalendarPicker.qml index d1b1d192..26dcfbc1 100644 --- a/src/controls/FluCalendarPicker.qml +++ b/src/controls/FluCalendarPicker.qml @@ -9,9 +9,10 @@ Rectangle { property color dividerColor: FluTheme.dark ? Qt.rgba(77/255,77/255,77/255,1) : Qt.rgba(239/255,239/255,239/255,1) property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) property color normalColor: FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(254/255,254/255,254/255,1) + property string text: "请选择日期" property var window : Window.window - id:root + id:control color: { if(mouse_area.containsMouse){ return hoverColor @@ -44,7 +45,7 @@ Rectangle { } verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - text:"请选择日期" + text:control.text } FluIcon{ @@ -95,15 +96,15 @@ Rectangle { } background: Item{} function showPopup() { - var pos = root.mapToItem(null, 0, 0) - if(window.height>pos.y+root.height+popup.height){ - popup.y = root.height + var pos = control.mapToItem(null, 0, 0) + if(window.height>pos.y+control.height+popup.height){ + popup.y = control.height } else if(pos.y>popup.height){ popup.y = -popup.height } else { popup.y = window.height-(pos.y+popup.height) } - popup.x = -(popup.width-root.width)/2 + popup.x = -(popup.width-control.width)/2 popup.open() } } diff --git a/src/controls/FluMultiLineTextBox.qml b/src/controls/FluMultiLineTextBox.qml index 9db02260..047d0b46 100644 --- a/src/controls/FluMultiLineTextBox.qml +++ b/src/controls/FluMultiLineTextBox.qml @@ -7,31 +7,32 @@ TextArea{ property int fontStyle: FluText.Body property int pixelSize : FluTheme.textSize property bool disabled: false + property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) - id:input + id:control width: 300 + enabled: !disabled color: { if(disabled){ - return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + return disableColor } - return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + return normalColor } - enabled: !disabled wrapMode: Text.WrapAnywhere renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering - selectByMouse: true selectionColor: FluTheme.primaryColor.lightest - background: FluTextBoxBackground{ - inputItem: input - } placeholderTextColor: { if(disabled){ - return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + return placeholderDisableColor } if(focus){ - return FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + return placeholderFocusColor } - return FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + return placeholderNormalColor } font.bold: { switch (fontStyle) { @@ -73,40 +74,15 @@ TextArea{ return text.pixelSize * 1.0 } } + selectByMouse: true + background: FluTextBoxBackground{ inputItem: control } TapHandler { acceptedButtons: Qt.RightButton - onTapped: input.echoMode !== TextInput.Password && menu.popup() + onTapped: control.echoMode !== TextInput.Password && menu.popup() } - FluMenu{ + FluTextBoxMenu{ id:menu - focus: false - FluMenuItem{ - text: "剪切" - visible: input.text !== "" - onClicked: { - input.cut() - } - } - FluMenuItem{ - text: "复制" - visible: input.selectedText !== "" - onClicked: { - input.copy() - } - } - FluMenuItem{ - text: "粘贴" - visible: input.canPaste - onClicked: { - input.paste() - } - } - FluMenuItem{ - text: "全选" - visible: input.text !== "" - onClicked: { - input.selectAll() - } - } + inputItem: control } + } diff --git a/src/controls/FluTabView.qml b/src/controls/FluTabView.qml index 043d3c31..f0b96084 100644 --- a/src/controls/FluTabView.qml +++ b/src/controls/FluTabView.qml @@ -131,7 +131,7 @@ Item { drag.target: item_container drag.axis: Drag.XAxis - onWheel: { + onWheel: (wheel)=>{ if (wheel.angleDelta.y > 0) scroll_nav.decrease() else scroll_nav.increase() } @@ -198,7 +198,7 @@ Item { } } function updatePosition(pos){ - var idx = tab_nav.indexAt(pos.x+tab_nav.contentX, pos.y) + var idx = tab_nav.indexAt(pos.x+tab_nav.contentX+1, pos.y) var firstIdx = tab_nav.indexAt(tab_nav.contentX+1, pos.y) var lastIdx = tab_nav.indexAt(tab_nav.width+tab_nav.contentX-1, pos.y) if(lastIdx === -1){ diff --git a/src/controls/FluTextBox.qml b/src/controls/FluTextBox.qml index 5cd395f8..d50ae233 100644 --- a/src/controls/FluTextBox.qml +++ b/src/controls/FluTextBox.qml @@ -7,26 +7,31 @@ TextField{ property int fontStyle: FluText.Body property int pixelSize : FluTheme.textSize property bool disabled: false + property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) - id:input + id:control width: 300 enabled: !disabled color: { if(disabled){ - return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + return disableColor } - return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + return normalColor } renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering selectionColor: FluTheme.primaryColor.lightest placeholderTextColor: { if(disabled){ - return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + return placeholderDisableColor } if(focus){ - return FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + return placeholderFocusColor } - return FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + return placeholderNormalColor } font.bold: { switch (fontStyle) { @@ -69,44 +74,14 @@ TextField{ } } selectByMouse: true - background: FluTextBoxBackground{ - inputItem: input - } + background: FluTextBoxBackground{ inputItem: control } TapHandler { acceptedButtons: Qt.RightButton - onTapped: input.echoMode !== TextInput.Password && menu.popup() + onTapped: control.echoMode !== TextInput.Password && menu.popup() } - FluMenu{ + FluTextBoxMenu{ id:menu - focus: false - FluMenuItem{ - text: "剪切" - visible: input.text !== "" - onClicked: { - input.cut() - } - } - FluMenuItem{ - text: "复制" - visible: input.selectedText !== "" - onClicked: { - input.copy() - } - } - FluMenuItem{ - text: "粘贴" - visible: input.canPaste - onClicked: { - input.paste() - } - } - FluMenuItem{ - text: "全选" - visible: input.text !== "" - onClicked: { - input.selectAll() - } - } + inputItem: control } } diff --git a/src/controls/FluTextBoxMenu.qml b/src/controls/FluTextBoxMenu.qml new file mode 100644 index 00000000..d4920f7f --- /dev/null +++ b/src/controls/FluTextBoxMenu.qml @@ -0,0 +1,40 @@ +import QtQuick +import FluentUI + +FluMenu{ + property string cutText : "剪切" + property string copyText : "复制" + property string pasteText : "粘贴" + property string selectAllText : "全选" + property var inputItem + id:menu + focus: false + FluMenuItem{ + text: cutText + visible: inputItem.text !== "" + onClicked: { + inputItem.cut() + } + } + FluMenuItem{ + text: copyText + visible: inputItem.selectedText !== "" + onClicked: { + inputItem.copy() + } + } + FluMenuItem{ + text: pasteText + visible: inputItem.canPaste + onClicked: { + inputItem.paste() + } + } + FluMenuItem{ + text: selectAllText + visible: inputItem.text !== "" + onClicked: { + inputItem.selectAll() + } + } +} diff --git a/src/res.qrc b/src/res.qrc index a9eaad43..922023aa 100644 --- a/src/res.qrc +++ b/src/res.qrc @@ -1,4 +1,4 @@ - + controls/FluButton.qml controls/FluFilledButton.qml @@ -23,7 +23,6 @@ controls/FluDivider.qml controls/FluTooltip.qml controls/FluTextBoxBackground.qml - controls/FluMultiLineTextBox.qml controls/FluWindowResize.qml controls/FluScrollBar.qml controls/FluMenu.qml @@ -60,5 +59,7 @@ controls/FluTabView.qml controls/FluItem.qml controls/FluPaneItemExpander.qml + controls/FluTextBoxMenu.qml + controls/FluMultilineTextBox.qml