├── example
├── linux
│ ├── .gitignore
│ ├── main.cc
│ ├── flutter
│ │ ├── generated_plugin_registrant.cc
│ │ ├── generated_plugin_registrant.h
│ │ ├── generated_plugins.cmake
│ │ └── CMakeLists.txt
│ ├── my_application.h
│ ├── my_application.cc
│ └── CMakeLists.txt
├── ios
│ ├── Flutter
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── AppFrameworkInfo.plist
│ ├── Runner
│ │ ├── Runner-Bridging-Header.h
│ │ ├── Assets.xcassets
│ │ │ ├── LaunchImage.imageset
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ ├── README.md
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.swift
│ │ ├── Base.lproj
│ │ │ ├── Main.storyboard
│ │ │ └── LaunchScreen.storyboard
│ │ └── Info.plist
│ ├── Runner.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── RunnerTests
│ │ └── RunnerTests.swift
│ └── .gitignore
├── macos
│ ├── Flutter
│ │ ├── Flutter-Debug.xcconfig
│ │ ├── Flutter-Release.xcconfig
│ │ └── GeneratedPluginRegistrant.swift
│ ├── Runner
│ │ ├── Configs
│ │ │ ├── Debug.xcconfig
│ │ │ ├── Release.xcconfig
│ │ │ ├── Warnings.xcconfig
│ │ │ └── AppInfo.xcconfig
│ │ ├── Assets.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ ├── app_icon_128.png
│ │ │ │ ├── app_icon_16.png
│ │ │ │ ├── app_icon_256.png
│ │ │ │ ├── app_icon_32.png
│ │ │ │ ├── app_icon_512.png
│ │ │ │ ├── app_icon_64.png
│ │ │ │ ├── app_icon_1024.png
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.swift
│ │ ├── Release.entitlements
│ │ ├── DebugProfile.entitlements
│ │ ├── MainFlutterWindow.swift
│ │ └── Info.plist
│ ├── .gitignore
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── Runner.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ └── RunnerTests
│ │ └── RunnerTests.swift
├── web
│ ├── favicon.png
│ ├── icons
│ │ ├── Icon-192.png
│ │ ├── Icon-512.png
│ │ ├── Icon-maskable-192.png
│ │ └── Icon-maskable-512.png
│ ├── manifest.json
│ └── index.html
├── android
│ ├── gradle.properties
│ ├── app
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── drawable
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── drawable-v21
│ │ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── values
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ └── values-night
│ │ │ │ │ │ └── styles.xml
│ │ │ │ ├── kotlin
│ │ │ │ │ └── com
│ │ │ │ │ │ └── oinarendra
│ │ │ │ │ │ └── multidropdownexample
│ │ │ │ │ │ └── example
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── AndroidManifest.xml
│ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── .gitignore
│ ├── settings.gradle
│ └── build.gradle
├── windows
│ ├── runner
│ │ ├── resources
│ │ │ └── app_icon.ico
│ │ ├── resource.h
│ │ ├── utils.h
│ │ ├── runner.exe.manifest
│ │ ├── flutter_window.h
│ │ ├── main.cpp
│ │ ├── CMakeLists.txt
│ │ ├── utils.cpp
│ │ ├── flutter_window.cpp
│ │ ├── Runner.rc
│ │ ├── win32_window.h
│ │ └── win32_window.cpp
│ ├── flutter
│ │ ├── generated_plugin_registrant.cc
│ │ ├── generated_plugin_registrant.h
│ │ ├── generated_plugins.cmake
│ │ └── CMakeLists.txt
│ ├── .gitignore
│ └── CMakeLists.txt
├── README.md
├── .gitignore
├── test
│ └── widget_test.dart
├── analysis_options.yaml
├── .metadata
├── pubspec.yaml
├── pubspec.lock
└── lib
│ └── main.dart
├── lib
├── multi_dropdown.dart
└── src
│ ├── enum
│ └── enums.dart
│ ├── controllers
│ ├── future_controller.dart
│ └── multiselect_controller.dart
│ ├── models
│ ├── network_request.dart
│ ├── dropdown_item.dart
│ └── decoration.dart
│ └── widgets
│ └── dropdown.dart
├── screenshots
├── screenshot_1.png
├── screenshot_2.png
├── screenshot_3.png
└── screenshot_4.png
├── test
└── multiselect_dropdown_test.dart
├── analysis_options.yaml
├── .metadata
├── .gitignore
├── pubspec.yaml
├── CHANGELOG.md
└── README.md
/example/linux/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral
2 |
--------------------------------------------------------------------------------
/lib/multi_dropdown.dart:
--------------------------------------------------------------------------------
1 | export 'src/multi_dropdown.dart';
2 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/web/favicon.png
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/screenshots/screenshot_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/screenshots/screenshot_1.png
--------------------------------------------------------------------------------
/screenshots/screenshot_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/screenshots/screenshot_2.png
--------------------------------------------------------------------------------
/screenshots/screenshot_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/screenshots/screenshot_3.png
--------------------------------------------------------------------------------
/screenshots/screenshot_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/screenshots/screenshot_4.png
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/dgph
7 | **/xcuserdata/
8 |
--------------------------------------------------------------------------------
/test/multiselect_dropdown_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_test/flutter_test.dart';
2 |
3 | void main() {
4 | test('', () {});
5 | }
6 |
--------------------------------------------------------------------------------
/example/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/example/windows/runner/resources/app_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/windows/runner/resources/app_icon.ico
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oi-narendra/multiselect-dropdown/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/linux/main.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | int main(int argc, char** argv) {
4 | g_autoptr(MyApplication) app = my_application_new();
5 | return g_application_run(G_APPLICATION(app), argc, argv);
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 |
9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
10 | }
11 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/oinarendra/multidropdownexample/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.oinarendra.multidropdownexample.example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/example/linux/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 |
10 | void fl_register_plugins(FlPluginRegistry* registry) {
11 | }
12 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
6 |
--------------------------------------------------------------------------------
/example/windows/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 |
10 | void RegisterPlugins(flutter::PluginRegistry* registry) {
11 | }
12 |
--------------------------------------------------------------------------------
/example/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @NSApplicationMain
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/example/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:very_good_analysis/analysis_options.yaml
2 |
3 | # Additional information about this file can be found at
4 | # https://dart.dev/guides/language/analysis-options
5 |
6 | linter:
7 | rules:
8 | lines_longer_than_80_chars: false
9 | avoid_equals_and_hash_code_on_mutable_classes: false
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 5464c5bac742001448fe4fc0597be939379f88ea
8 | channel: stable
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/example/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/example/macos/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import FlutterMacOS
2 | import Cocoa
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/example/windows/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral/
2 |
3 | # Visual Studio user-specific files.
4 | *.suo
5 | *.user
6 | *.userosscache
7 | *.sln.docstates
8 |
9 | # Visual Studio build-related files.
10 | x64/
11 | x86/
12 |
13 | # Visual Studio cache files
14 | # files ending in .cache can be ignored
15 | *.[Cc]ache
16 | # but keep track of directories ending in .cache
17 | !*.[Cc]ache/
18 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/example/linux/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void fl_register_plugins(FlPluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/example/windows/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void RegisterPlugins(flutter::PluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/macos/Runner/DebugProfile.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 | com.apple.security.network.server
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController()
7 | let windowFrame = self.frame
8 | self.contentViewController = flutterViewController
9 | self.setFrame(windowFrame, display: true)
10 |
11 | RegisterGeneratedPlugins(registry: flutterViewController)
12 |
13 | super.awakeFromNib()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/linux/my_application.h:
--------------------------------------------------------------------------------
1 | #ifndef FLUTTER_MY_APPLICATION_H_
2 | #define FLUTTER_MY_APPLICATION_H_
3 |
4 | #include
5 |
6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
7 | GtkApplication)
8 |
9 | /**
10 | * my_application_new:
11 | *
12 | * Creates a new Flutter-based application.
13 | *
14 | * Returns: a new #MyApplication.
15 | */
16 | MyApplication* my_application_new();
17 |
18 | #endif // FLUTTER_MY_APPLICATION_H_
19 |
--------------------------------------------------------------------------------
/example/windows/runner/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by Runner.rc
4 | //
5 | #define IDI_APP_ICON 101
6 |
7 | // Next default values for new objects
8 | //
9 | #ifdef APSTUDIO_INVOKED
10 | #ifndef APSTUDIO_READONLY_SYMBOLS
11 | #define _APS_NEXT_RESOURCE_VALUE 102
12 | #define _APS_NEXT_COMMAND_VALUE 40001
13 | #define _APS_NEXT_CONTROL_VALUE 1001
14 | #define _APS_NEXT_SYMED_VALUE 101
15 | #endif
16 | #endif
17 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/src/enum/enums.dart:
--------------------------------------------------------------------------------
1 | part of '../multi_dropdown.dart';
2 |
3 | /// [RequestMethod]
4 | /// RequestMethod enum for the request method of the dropdown items.
5 | /// * [RequestMethod.get]: get request
6 | /// * [RequestMethod.post]: post request
7 | /// * [RequestMethod.put]: put request
8 | /// * [RequestMethod.delete]: delete request
9 | /// * [RequestMethod.patch]: patch request
10 | enum RequestMethod {
11 | /// get request
12 | get,
13 |
14 | /// post request
15 | post,
16 |
17 | /// put request
18 | put,
19 |
20 | /// patch request
21 | patch,
22 |
23 | /// delete request
24 | delete
25 | }
26 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # example
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
13 |
14 | For help getting started with Flutter development, view the
15 | [online documentation](https://docs.flutter.dev/), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/Warnings.xcconfig:
--------------------------------------------------------------------------------
1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
2 | GCC_WARN_UNDECLARED_SELECTOR = YES
3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
6 | CLANG_WARN_PRAGMA_PACK = YES
7 | CLANG_WARN_STRICT_PROTOTYPES = YES
8 | CLANG_WARN_COMMA = YES
9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES
10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
12 | GCC_WARN_SHADOW = YES
13 | CLANG_WARN_UNREACHABLE_CODE = YES
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
25 | /pubspec.lock
26 | **/doc/api/
27 | .dart_tool/
28 | .packages
29 | build/
30 |
31 |
32 | .vscode
--------------------------------------------------------------------------------
/lib/src/controllers/future_controller.dart:
--------------------------------------------------------------------------------
1 | part of '../multi_dropdown.dart';
2 |
3 | /// Controller for the future.
4 | ///
5 | /// This controller is used to control the future state of the dropdown.
6 | /// It can be used to start, stop, or toggle the future state of the dropdown.
7 | class _FutureController extends ValueNotifier {
8 | _FutureController() : super(false);
9 |
10 | /// Sets the controller to true.
11 | void start() {
12 | value = true;
13 | }
14 |
15 | /// Sets the controller to false.
16 | void stop() {
17 | value = false;
18 | }
19 |
20 | /// Toggles the controller.
21 | void toggle() {
22 | value = !value;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/example/macos/Runner/Configs/AppInfo.xcconfig:
--------------------------------------------------------------------------------
1 | // Application-level settings for the Runner target.
2 | //
3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
4 | // future. If not, the values below would default to using the project name when this becomes a
5 | // 'flutter create' template.
6 |
7 | // The application's name. By default this is also the title of the Flutter window.
8 | PRODUCT_NAME = example
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.oinarendra.multidropdownexample.example
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2023 com.oinarendra.multidropdownexample. All rights reserved.
15 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.7.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:7.3.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | mavenCentral()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | tasks.register("clean", Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/example/windows/runner/utils.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_UTILS_H_
2 | #define RUNNER_UTILS_H_
3 |
4 | #include
5 | #include
6 |
7 | // Creates a console for the process, and redirects stdout and stderr to
8 | // it for both the runner and the Flutter library.
9 | void CreateAndAttachConsole();
10 |
11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
12 | // encoded in UTF-8. Returns an empty std::string on failure.
13 | std::string Utf8FromUtf16(const wchar_t* utf16_string);
14 |
15 | // Gets the command line arguments passed in as a std::vector,
16 | // encoded in UTF-8. Returns an empty std::vector on failure.
17 | std::vector GetCommandLineArguments();
18 |
19 | #endif // RUNNER_UTILS_H_
20 |
--------------------------------------------------------------------------------
/example/linux/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | )
7 |
8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
9 | )
10 |
11 | set(PLUGIN_BUNDLED_LIBRARIES)
12 |
13 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
18 | endforeach(plugin)
19 |
20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
23 | endforeach(ffi_plugin)
24 |
--------------------------------------------------------------------------------
/example/windows/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | )
7 |
8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
9 | )
10 |
11 | set(PLUGIN_BUNDLED_LIBRARIES)
12 |
13 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
18 | endforeach(plugin)
19 |
20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
23 | endforeach(ffi_plugin)
24 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Symbolication related
36 | app.*.symbols
37 |
38 | # Obfuscation related
39 | app.*.map.json
40 |
41 | # Android Studio will place build artifacts here
42 | /android/app/debug
43 | /android/app/profile
44 | /android/app/release
45 |
--------------------------------------------------------------------------------
/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/windows/runner/runner.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PerMonitorV2
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/example/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "short_name": "example",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/example/windows/runner/flutter_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_FLUTTER_WINDOW_H_
2 | #define RUNNER_FLUTTER_WINDOW_H_
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include "win32_window.h"
10 |
11 | // A window that does nothing but host a Flutter view.
12 | class FlutterWindow : public Win32Window {
13 | public:
14 | // Creates a new FlutterWindow hosting a Flutter view running |project|.
15 | explicit FlutterWindow(const flutter::DartProject& project);
16 | virtual ~FlutterWindow();
17 |
18 | protected:
19 | // Win32Window:
20 | bool OnCreate() override;
21 | void OnDestroy() override;
22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
23 | LPARAM const lparam) noexcept override;
24 |
25 | private:
26 | // The project to run.
27 | flutter::DartProject project_;
28 |
29 | // The Flutter instance hosted by this window.
30 | std::unique_ptr flutter_controller_;
31 | };
32 |
33 | #endif // RUNNER_FLUTTER_WINDOW_H_
34 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility in the flutter_test package. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:example/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(const MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/example/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | $(PRODUCT_COPYRIGHT)
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/windows/runner/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "flutter_window.h"
6 | #include "utils.h"
7 |
8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
9 | _In_ wchar_t *command_line, _In_ int show_command) {
10 | // Attach to console when present (e.g., 'flutter run') or create a
11 | // new console when running with a debugger.
12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
13 | CreateAndAttachConsole();
14 | }
15 |
16 | // Initialize COM, so that it is available for use in the library and/or
17 | // plugins.
18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
19 |
20 | flutter::DartProject project(L"data");
21 |
22 | std::vector command_line_arguments =
23 | GetCommandLineArguments();
24 |
25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
26 |
27 | FlutterWindow window(project);
28 | Win32Window::Point origin(10, 10);
29 | Win32Window::Size size(1280, 720);
30 | if (!window.Create(L"example", origin, size)) {
31 | return EXIT_FAILURE;
32 | }
33 | window.SetQuitOnClose(true);
34 |
35 | ::MSG msg;
36 | while (::GetMessage(&msg, nullptr, 0, 0)) {
37 | ::TranslateMessage(&msg);
38 | ::DispatchMessage(&msg);
39 | }
40 |
41 | ::CoUninitialize();
42 | return EXIT_SUCCESS;
43 | }
44 |
--------------------------------------------------------------------------------
/example/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at
17 | # https://dart-lang.github.io/linter/lints/index.html.
18 | #
19 | # Instead of disabling a lint rule for the entire project in the
20 | # section below, it can also be suppressed for a single line of code
21 | # or a specific dart file by using the `// ignore: name_of_lint` and
22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
23 | # producing the lint.
24 | rules:
25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27 |
28 | # Additional information about this file can be found at
29 | # https://dart.dev/guides/language/analysis-options
30 |
--------------------------------------------------------------------------------
/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "app_icon_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "app_icon_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "app_icon_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "app_icon_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "app_icon_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "app_icon_256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "app_icon_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "app_icon_512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "app_icon_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "app_icon_1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/src/models/network_request.dart:
--------------------------------------------------------------------------------
1 | // import 'dart:async';
2 |
3 | // import 'package:flutter/material.dart';
4 | // import 'package:multi_dropdown/src/enum/app_enums.dart';
5 | // import 'package:multi_dropdown/src/models/dropdown_item.dart';
6 |
7 | // /// Configuration for the network.
8 | // ///
9 | // /// [url] is the url of the network.
10 | // /// [method] is the request method of the network.
11 | // /// [headers] is the headers of the network.
12 | // /// [body] is the body of the network.
13 | // /// [queryParameters] is the query parameters of the network.
14 |
15 | // class NetworkRequest {
16 | // NetworkRequest({
17 | // required this.url,
18 | // this.method = RequestMethod.get,
19 | // this.headers = const {},
20 | // this.body,
21 | // this.queryParameters = const {},
22 | // this.responseParser,
23 | // this.responseErrorBuilder,
24 | // }) : customRequest = null;
25 |
26 | // NetworkRequest.custom({
27 | // this.responseErrorBuilder,
28 | // this.customRequest,
29 | // }) : url = '',
30 | // method = RequestMethod.get,
31 | // headers = const {},
32 | // body = const {},
33 | // queryParameters = const {},
34 | // responseParser = null;
35 | // final String url;
36 | // final RequestMethod method;
37 | // final Map? headers;
38 | // final Map? body;
39 | // final Map? queryParameters;
40 | // final Future>>? Function()? customRequest;
41 | // final Future>> Function(dynamic response)? responseParser;
42 | // final Widget Function(BuildContext context, dynamic response)?
43 | // responseErrorBuilder;
44 | // }
45 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
14 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
29 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: 796c8ef79279f9c774545b3771238c3098dbefab
8 | channel: stable
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
17 | base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
18 | - platform: android
19 | create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
20 | base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
21 | - platform: ios
22 | create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
23 | base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
24 | - platform: linux
25 | create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
26 | base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
27 | - platform: macos
28 | create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
29 | base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
30 | - platform: web
31 | create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
32 | base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
33 | - platform: windows
34 | create_revision: 796c8ef79279f9c774545b3771238c3098dbefab
35 | base_revision: 796c8ef79279f9c774545b3771238c3098dbefab
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Example
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | example
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | UIViewControllerBasedStatusBarAppearance
45 |
46 | CADisableMinimumFrameDurationOnPhone
47 |
48 | UIApplicationSupportsIndirectInputEvents
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/example/windows/runner/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.14)
2 | project(runner LANGUAGES CXX)
3 |
4 | # Define the application target. To change its name, change BINARY_NAME in the
5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
6 | # work.
7 | #
8 | # Any new source files that you add to the application should be added here.
9 | add_executable(${BINARY_NAME} WIN32
10 | "flutter_window.cpp"
11 | "main.cpp"
12 | "utils.cpp"
13 | "win32_window.cpp"
14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
15 | "Runner.rc"
16 | "runner.exe.manifest"
17 | )
18 |
19 | # Apply the standard set of build settings. This can be removed for applications
20 | # that need different build settings.
21 | apply_standard_settings(${BINARY_NAME})
22 |
23 | # Add preprocessor definitions for the build version.
24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
29 |
30 | # Disable Windows macros that collide with C++ standard library functions.
31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
32 |
33 | # Add dependency libraries and include directories. Add any application-specific
34 | # dependencies here.
35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
38 |
39 | # Run the Flutter tool portions of the build. This must not be removed.
40 | add_dependencies(${BINARY_NAME} flutter_assemble)
41 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: multi_dropdown
2 | description: "Streamlined Flutter widget for versatile multi-selection with extensive customization."
3 | version: 3.0.1
4 | homepage: "https://github.com/oi-narendra/multiselect-dropdown"
5 |
6 | environment:
7 | sdk: ">=2.16.2 <4.0.0"
8 | flutter: ">=1.17.0"
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 |
14 | dev_dependencies:
15 | flutter_lints: ^4.0.0
16 | flutter_test:
17 | sdk: flutter
18 | lint: ^2.3.0
19 | very_good_analysis: ^6.0.0
20 |
21 | # For information on the generic Dart part of this file, see the
22 | # following page: https://dart.dev/tools/pub/pubspec
23 | # The following section is specific to Flutter.
24 | flutter: null
25 | # To add assets to your package, add an assets section, like this:
26 | # assets:
27 | # - images/a_dot_burr.jpeg
28 | # - images/a_dot_ham.jpeg
29 | #
30 | # For details regarding assets in packages, see
31 | # https://flutter.dev/assets-and-images/#from-packages
32 | #
33 | # An image asset can refer to one or more resolution-specific "variants", see
34 | # https://flutter.dev/assets-and-images/#resolution-aware.
35 | # To add custom fonts to your package, add a fonts section here,
36 | # in this "flutter" section. Each entry in this list should have a
37 | # "family" key with the font family name, and a "fonts" key with a
38 | # list giving the asset and other descriptors for the font. For
39 | # example:
40 | # fonts:
41 | # - family: Schyler
42 | # fonts:
43 | # - asset: fonts/Schyler-Regular.ttf
44 | # - asset: fonts/Schyler-Italic.ttf
45 | # style: italic
46 | # - family: Trajan Pro
47 | # fonts:
48 | # - asset: fonts/TrajanPro.ttf
49 | # - asset: fonts/TrajanPro_Bold.ttf
50 | # weight: 700
51 | #
52 | # For details regarding fonts in packages, see
53 | # https://flutter.dev/custom-fonts/#from-packages
54 | screenshots:
55 | - description: "Example screenshot 1"
56 | path: screenshots/screenshot_2.png
57 |
--------------------------------------------------------------------------------
/example/windows/runner/utils.cpp:
--------------------------------------------------------------------------------
1 | #include "utils.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | void CreateAndAttachConsole() {
11 | if (::AllocConsole()) {
12 | FILE *unused;
13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
14 | _dup2(_fileno(stdout), 1);
15 | }
16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
17 | _dup2(_fileno(stdout), 2);
18 | }
19 | std::ios::sync_with_stdio();
20 | FlutterDesktopResyncOutputStreams();
21 | }
22 | }
23 |
24 | std::vector GetCommandLineArguments() {
25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
26 | int argc;
27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
28 | if (argv == nullptr) {
29 | return std::vector();
30 | }
31 |
32 | std::vector command_line_arguments;
33 |
34 | // Skip the first argument as it's the binary name.
35 | for (int i = 1; i < argc; i++) {
36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
37 | }
38 |
39 | ::LocalFree(argv);
40 |
41 | return command_line_arguments;
42 | }
43 |
44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) {
45 | if (utf16_string == nullptr) {
46 | return std::string();
47 | }
48 | int target_length = ::WideCharToMultiByte(
49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
50 | -1, nullptr, 0, nullptr, nullptr)
51 | -1; // remove the trailing null character
52 | int input_length = (int)wcslen(utf16_string);
53 | std::string utf8_string;
54 | if (target_length <= 0 || target_length > utf8_string.max_size()) {
55 | return utf8_string;
56 | }
57 | utf8_string.resize(target_length);
58 | int converted_length = ::WideCharToMultiByte(
59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
60 | input_length, utf8_string.data(), target_length, nullptr, nullptr);
61 | if (converted_length == 0) {
62 | return std::string();
63 | }
64 | return utf8_string;
65 | }
66 |
--------------------------------------------------------------------------------
/example/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | example
33 |
34 |
35 |
39 |
40 |
41 |
42 |
43 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/example/windows/runner/flutter_window.cpp:
--------------------------------------------------------------------------------
1 | #include "flutter_window.h"
2 |
3 | #include
4 |
5 | #include "flutter/generated_plugin_registrant.h"
6 |
7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project)
8 | : project_(project) {}
9 |
10 | FlutterWindow::~FlutterWindow() {}
11 |
12 | bool FlutterWindow::OnCreate() {
13 | if (!Win32Window::OnCreate()) {
14 | return false;
15 | }
16 |
17 | RECT frame = GetClientArea();
18 |
19 | // The size here must match the window dimensions to avoid unnecessary surface
20 | // creation / destruction in the startup path.
21 | flutter_controller_ = std::make_unique(
22 | frame.right - frame.left, frame.bottom - frame.top, project_);
23 | // Ensure that basic setup of the controller was successful.
24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) {
25 | return false;
26 | }
27 | RegisterPlugins(flutter_controller_->engine());
28 | SetChildContent(flutter_controller_->view()->GetNativeWindow());
29 |
30 | flutter_controller_->engine()->SetNextFrameCallback([&]() {
31 | this->Show();
32 | });
33 |
34 | return true;
35 | }
36 |
37 | void FlutterWindow::OnDestroy() {
38 | if (flutter_controller_) {
39 | flutter_controller_ = nullptr;
40 | }
41 |
42 | Win32Window::OnDestroy();
43 | }
44 |
45 | LRESULT
46 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
47 | WPARAM const wparam,
48 | LPARAM const lparam) noexcept {
49 | // Give Flutter, including plugins, an opportunity to handle window messages.
50 | if (flutter_controller_) {
51 | std::optional result =
52 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
53 | lparam);
54 | if (result) {
55 | return *result;
56 | }
57 | }
58 |
59 | switch (message) {
60 | case WM_FONTCHANGE:
61 | flutter_controller_->engine()->ReloadSystemFonts();
62 | break;
63 | }
64 |
65 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
66 | }
67 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | namespace "com.oinarendra.multidropdownexample.example"
30 | compileSdkVersion flutter.compileSdkVersion
31 | ndkVersion flutter.ndkVersion
32 |
33 | compileOptions {
34 | sourceCompatibility JavaVersion.VERSION_1_8
35 | targetCompatibility JavaVersion.VERSION_1_8
36 | }
37 |
38 | kotlinOptions {
39 | jvmTarget = '1.8'
40 | }
41 |
42 | sourceSets {
43 | main.java.srcDirs += 'src/main/kotlin'
44 | }
45 |
46 | defaultConfig {
47 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
48 | applicationId "com.oinarendra.multidropdownexample.example"
49 | // You can update the following values to match your application needs.
50 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
51 | minSdkVersion flutter.minSdkVersion
52 | targetSdkVersion flutter.targetSdkVersion
53 | versionCode flutterVersionCode.toInteger()
54 | versionName flutterVersionName
55 | }
56 |
57 | buildTypes {
58 | release {
59 | // TODO: Add your own signing config for the release build.
60 | // Signing with the debug keys for now, so `flutter run --release` works.
61 | signingConfig signingConfigs.debug
62 | }
63 | }
64 | }
65 |
66 | flutter {
67 | source '../..'
68 | }
69 |
70 | dependencies {
71 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
72 | }
73 |
--------------------------------------------------------------------------------
/example/linux/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This file controls Flutter-level build steps. It should not be edited.
2 | cmake_minimum_required(VERSION 3.10)
3 |
4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5 |
6 | # Configuration provided via flutter tool.
7 | include(${EPHEMERAL_DIR}/generated_config.cmake)
8 |
9 | # TODO: Move the rest of this into files in ephemeral. See
10 | # https://github.com/flutter/flutter/issues/57146.
11 |
12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...),
13 | # which isn't available in 3.10.
14 | function(list_prepend LIST_NAME PREFIX)
15 | set(NEW_LIST "")
16 | foreach(element ${${LIST_NAME}})
17 | list(APPEND NEW_LIST "${PREFIX}${element}")
18 | endforeach(element)
19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
20 | endfunction()
21 |
22 | # === Flutter Library ===
23 | # System-level dependencies.
24 | find_package(PkgConfig REQUIRED)
25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
28 |
29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
30 |
31 | # Published to parent scope for install step.
32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
36 |
37 | list(APPEND FLUTTER_LIBRARY_HEADERS
38 | "fl_basic_message_channel.h"
39 | "fl_binary_codec.h"
40 | "fl_binary_messenger.h"
41 | "fl_dart_project.h"
42 | "fl_engine.h"
43 | "fl_json_message_codec.h"
44 | "fl_json_method_codec.h"
45 | "fl_message_codec.h"
46 | "fl_method_call.h"
47 | "fl_method_channel.h"
48 | "fl_method_codec.h"
49 | "fl_method_response.h"
50 | "fl_plugin_registrar.h"
51 | "fl_plugin_registry.h"
52 | "fl_standard_message_codec.h"
53 | "fl_standard_method_codec.h"
54 | "fl_string_codec.h"
55 | "fl_value.h"
56 | "fl_view.h"
57 | "flutter_linux.h"
58 | )
59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
60 | add_library(flutter INTERFACE)
61 | target_include_directories(flutter INTERFACE
62 | "${EPHEMERAL_DIR}"
63 | )
64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
65 | target_link_libraries(flutter INTERFACE
66 | PkgConfig::GTK
67 | PkgConfig::GLIB
68 | PkgConfig::GIO
69 | )
70 | add_dependencies(flutter flutter_assemble)
71 |
72 | # === Flutter tool backend ===
73 | # _phony_ is a non-existent file to force this command to run every time,
74 | # since currently there's no way to get a full input/output list from the
75 | # flutter tool.
76 | add_custom_command(
77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_
79 | COMMAND ${CMAKE_COMMAND} -E env
80 | ${FLUTTER_TOOL_ENVIRONMENT}
81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
83 | VERBATIM
84 | )
85 | add_custom_target(flutter_assemble DEPENDS
86 | "${FLUTTER_LIBRARY}"
87 | ${FLUTTER_LIBRARY_HEADERS}
88 | )
89 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/lib/src/models/dropdown_item.dart:
--------------------------------------------------------------------------------
1 | part of '../multi_dropdown.dart';
2 |
3 | /// Represents an item in a dropdown menu.
4 | class DropdownItem {
5 | /// Creates a new instance of [DropdownItem].
6 | ///
7 | /// The [label] and [value] parameters are required.
8 | /// The [disabled] and [selected] parameters are optional and default to false.
9 | DropdownItem({
10 | required this.label,
11 | required this.value,
12 | this.disabled = false,
13 | this.selected = false,
14 | });
15 |
16 | /// Creates a new instance of [DropdownItem] from a map.
17 | ///
18 | /// The map should contain the following keys:
19 | /// - 'label': The label of the dropdown item (required).
20 | /// - 'value': The value associated with the dropdown item (required).
21 | /// - 'disabled': Indicates whether the dropdown item is disabled (optional, default is false).
22 | /// - 'selected': Indicates whether the dropdown item is selected (optional, default is false).
23 | factory DropdownItem.fromMap(Map map) {
24 | return DropdownItem(
25 | label: map['label'] as String? ?? '',
26 | value: map['value'] as T,
27 | disabled: map['disabled'] as bool? ?? false,
28 | selected: map['selected'] as bool? ?? false,
29 | );
30 | }
31 |
32 | /// The label of the dropdown item.
33 | final String label;
34 |
35 | /// The value associated with the dropdown item.
36 | final T value;
37 |
38 | /// Indicates whether the dropdown item is disabled.
39 | bool disabled;
40 |
41 | /// Indicates whether the dropdown item is selected.
42 | bool selected;
43 |
44 | /// Converts the [DropdownItem] instance to a map.
45 | ///
46 | /// The returned map will contain the following keys:
47 | /// - 'label': The label of the dropdown item.
48 | /// - 'value': The value associated with the dropdown item.
49 | /// - 'disabled': Indicates whether the dropdown item is disabled.
50 | /// - 'selected': Indicates whether the dropdown item is selected.
51 | Map toMap() {
52 | return {
53 | 'label': label,
54 | 'value': value,
55 | 'disabled': disabled,
56 | 'selected': selected,
57 | };
58 | }
59 |
60 | /// Converts the [DropdownItem] instance to a JSON string.
61 | String toJson() => jsonEncode(toMap);
62 |
63 | @override
64 | String toString() {
65 | return 'ValueItem(label: $label, value: $value, disabled: $disabled, selected: $selected)';
66 | }
67 |
68 | @override
69 | bool operator ==(Object other) {
70 | if (identical(this, other)) return true;
71 |
72 | return other is DropdownItem &&
73 | other.label == label &&
74 | other.value == value &&
75 | other.disabled == disabled &&
76 | other.selected == selected;
77 | }
78 |
79 | @override
80 | int get hashCode =>
81 | label.hashCode ^ value.hashCode ^ disabled.hashCode ^ selected.hashCode;
82 |
83 | /// Creates a copy of the [DropdownItem] instance with the specified properties.
84 | ///
85 | /// If any of the properties are not provided, the corresponding properties of the original instance will be used.
86 | DropdownItem copyWith({
87 | String? label,
88 | T? value,
89 | bool? disabled,
90 | bool? selected,
91 | }) {
92 | return DropdownItem(
93 | label: label ?? this.label,
94 | value: value ?? this.value,
95 | disabled: disabled ?? this.disabled,
96 | selected: selected ?? this.selected,
97 | );
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/example/windows/runner/Runner.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #pragma code_page(65001)
4 | #include "resource.h"
5 |
6 | #define APSTUDIO_READONLY_SYMBOLS
7 | /////////////////////////////////////////////////////////////////////////////
8 | //
9 | // Generated from the TEXTINCLUDE 2 resource.
10 | //
11 | #include "winres.h"
12 |
13 | /////////////////////////////////////////////////////////////////////////////
14 | #undef APSTUDIO_READONLY_SYMBOLS
15 |
16 | /////////////////////////////////////////////////////////////////////////////
17 | // English (United States) resources
18 |
19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Icon
51 | //
52 |
53 | // Icon with lowest ID value placed first to ensure application icon
54 | // remains consistent on all systems.
55 | IDI_APP_ICON ICON "resources\\app_icon.ico"
56 |
57 |
58 | /////////////////////////////////////////////////////////////////////////////
59 | //
60 | // Version
61 | //
62 |
63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
65 | #else
66 | #define VERSION_AS_NUMBER 1,0,0,0
67 | #endif
68 |
69 | #if defined(FLUTTER_VERSION)
70 | #define VERSION_AS_STRING FLUTTER_VERSION
71 | #else
72 | #define VERSION_AS_STRING "1.0.0"
73 | #endif
74 |
75 | VS_VERSION_INFO VERSIONINFO
76 | FILEVERSION VERSION_AS_NUMBER
77 | PRODUCTVERSION VERSION_AS_NUMBER
78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
79 | #ifdef _DEBUG
80 | FILEFLAGS VS_FF_DEBUG
81 | #else
82 | FILEFLAGS 0x0L
83 | #endif
84 | FILEOS VOS__WINDOWS32
85 | FILETYPE VFT_APP
86 | FILESUBTYPE 0x0L
87 | BEGIN
88 | BLOCK "StringFileInfo"
89 | BEGIN
90 | BLOCK "040904e4"
91 | BEGIN
92 | VALUE "CompanyName", "com.oinarendra.multidropdownexample" "\0"
93 | VALUE "FileDescription", "example" "\0"
94 | VALUE "FileVersion", VERSION_AS_STRING "\0"
95 | VALUE "InternalName", "example" "\0"
96 | VALUE "LegalCopyright", "Copyright (C) 2023 com.oinarendra.multidropdownexample. All rights reserved." "\0"
97 | VALUE "OriginalFilename", "example.exe" "\0"
98 | VALUE "ProductName", "example" "\0"
99 | VALUE "ProductVersion", VERSION_AS_STRING "\0"
100 | END
101 | END
102 | BLOCK "VarFileInfo"
103 | BEGIN
104 | VALUE "Translation", 0x409, 1252
105 | END
106 | END
107 |
108 | #endif // English (United States) resources
109 | /////////////////////////////////////////////////////////////////////////////
110 |
111 |
112 |
113 | #ifndef APSTUDIO_INVOKED
114 | /////////////////////////////////////////////////////////////////////////////
115 | //
116 | // Generated from the TEXTINCLUDE 3 resource.
117 | //
118 |
119 |
120 | /////////////////////////////////////////////////////////////////////////////
121 | #endif // not APSTUDIO_INVOKED
122 |
--------------------------------------------------------------------------------
/example/windows/runner/win32_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_WIN32_WINDOW_H_
2 | #define RUNNER_WIN32_WINDOW_H_
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be
11 | // inherited from by classes that wish to specialize with custom
12 | // rendering and input handling
13 | class Win32Window {
14 | public:
15 | struct Point {
16 | unsigned int x;
17 | unsigned int y;
18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {}
19 | };
20 |
21 | struct Size {
22 | unsigned int width;
23 | unsigned int height;
24 | Size(unsigned int width, unsigned int height)
25 | : width(width), height(height) {}
26 | };
27 |
28 | Win32Window();
29 | virtual ~Win32Window();
30 |
31 | // Creates a win32 window with |title| that is positioned and sized using
32 | // |origin| and |size|. New windows are created on the default monitor. Window
33 | // sizes are specified to the OS in physical pixels, hence to ensure a
34 | // consistent size this function will scale the inputted width and height as
35 | // as appropriate for the default monitor. The window is invisible until
36 | // |Show| is called. Returns true if the window was created successfully.
37 | bool Create(const std::wstring& title, const Point& origin, const Size& size);
38 |
39 | // Show the current window. Returns true if the window was successfully shown.
40 | bool Show();
41 |
42 | // Release OS resources associated with window.
43 | void Destroy();
44 |
45 | // Inserts |content| into the window tree.
46 | void SetChildContent(HWND content);
47 |
48 | // Returns the backing Window handle to enable clients to set icon and other
49 | // window properties. Returns nullptr if the window has been destroyed.
50 | HWND GetHandle();
51 |
52 | // If true, closing this window will quit the application.
53 | void SetQuitOnClose(bool quit_on_close);
54 |
55 | // Return a RECT representing the bounds of the current client area.
56 | RECT GetClientArea();
57 |
58 | protected:
59 | // Processes and route salient window messages for mouse handling,
60 | // size change and DPI. Delegates handling of these to member overloads that
61 | // inheriting classes can handle.
62 | virtual LRESULT MessageHandler(HWND window,
63 | UINT const message,
64 | WPARAM const wparam,
65 | LPARAM const lparam) noexcept;
66 |
67 | // Called when CreateAndShow is called, allowing subclass window-related
68 | // setup. Subclasses should return false if setup fails.
69 | virtual bool OnCreate();
70 |
71 | // Called when Destroy is called.
72 | virtual void OnDestroy();
73 |
74 | private:
75 | friend class WindowClassRegistrar;
76 |
77 | // OS callback called by message pump. Handles the WM_NCCREATE message which
78 | // is passed when the non-client area is being created and enables automatic
79 | // non-client DPI scaling so that the non-client area automatically
80 | // responds to changes in DPI. All other messages are handled by
81 | // MessageHandler.
82 | static LRESULT CALLBACK WndProc(HWND const window,
83 | UINT const message,
84 | WPARAM const wparam,
85 | LPARAM const lparam) noexcept;
86 |
87 | // Retrieves a class instance pointer for |window|
88 | static Win32Window* GetThisFromHandle(HWND const window) noexcept;
89 |
90 | // Update the window frame's theme to match the system theme.
91 | static void UpdateTheme(HWND const window);
92 |
93 | bool quit_on_close_ = false;
94 |
95 | // window handle for top level window.
96 | HWND window_handle_ = nullptr;
97 |
98 | // window handle for hosted content.
99 | HWND child_content_ = nullptr;
100 | };
101 |
102 | #endif // RUNNER_WIN32_WINDOW_H_
103 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/example/windows/flutter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This file controls Flutter-level build steps. It should not be edited.
2 | cmake_minimum_required(VERSION 3.14)
3 |
4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
5 |
6 | # Configuration provided via flutter tool.
7 | include(${EPHEMERAL_DIR}/generated_config.cmake)
8 |
9 | # TODO: Move the rest of this into files in ephemeral. See
10 | # https://github.com/flutter/flutter/issues/57146.
11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
12 |
13 | # === Flutter Library ===
14 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
15 |
16 | # Published to parent scope for install step.
17 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
18 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
19 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
20 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
21 |
22 | list(APPEND FLUTTER_LIBRARY_HEADERS
23 | "flutter_export.h"
24 | "flutter_windows.h"
25 | "flutter_messenger.h"
26 | "flutter_plugin_registrar.h"
27 | "flutter_texture_registrar.h"
28 | )
29 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
30 | add_library(flutter INTERFACE)
31 | target_include_directories(flutter INTERFACE
32 | "${EPHEMERAL_DIR}"
33 | )
34 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
35 | add_dependencies(flutter flutter_assemble)
36 |
37 | # === Wrapper ===
38 | list(APPEND CPP_WRAPPER_SOURCES_CORE
39 | "core_implementations.cc"
40 | "standard_codec.cc"
41 | )
42 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
43 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
44 | "plugin_registrar.cc"
45 | )
46 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
47 | list(APPEND CPP_WRAPPER_SOURCES_APP
48 | "flutter_engine.cc"
49 | "flutter_view_controller.cc"
50 | )
51 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
52 |
53 | # Wrapper sources needed for a plugin.
54 | add_library(flutter_wrapper_plugin STATIC
55 | ${CPP_WRAPPER_SOURCES_CORE}
56 | ${CPP_WRAPPER_SOURCES_PLUGIN}
57 | )
58 | apply_standard_settings(flutter_wrapper_plugin)
59 | set_target_properties(flutter_wrapper_plugin PROPERTIES
60 | POSITION_INDEPENDENT_CODE ON)
61 | set_target_properties(flutter_wrapper_plugin PROPERTIES
62 | CXX_VISIBILITY_PRESET hidden)
63 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
64 | target_include_directories(flutter_wrapper_plugin PUBLIC
65 | "${WRAPPER_ROOT}/include"
66 | )
67 | add_dependencies(flutter_wrapper_plugin flutter_assemble)
68 |
69 | # Wrapper sources needed for the runner.
70 | add_library(flutter_wrapper_app STATIC
71 | ${CPP_WRAPPER_SOURCES_CORE}
72 | ${CPP_WRAPPER_SOURCES_APP}
73 | )
74 | apply_standard_settings(flutter_wrapper_app)
75 | target_link_libraries(flutter_wrapper_app PUBLIC flutter)
76 | target_include_directories(flutter_wrapper_app PUBLIC
77 | "${WRAPPER_ROOT}/include"
78 | )
79 | add_dependencies(flutter_wrapper_app flutter_assemble)
80 |
81 | # === Flutter tool backend ===
82 | # _phony_ is a non-existent file to force this command to run every time,
83 | # since currently there's no way to get a full input/output list from the
84 | # flutter tool.
85 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
86 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
87 | add_custom_command(
88 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
89 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
90 | ${CPP_WRAPPER_SOURCES_APP}
91 | ${PHONY_OUTPUT}
92 | COMMAND ${CMAKE_COMMAND} -E env
93 | ${FLUTTER_TOOL_ENVIRONMENT}
94 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
95 | windows-x64 $
96 | VERBATIM
97 | )
98 | add_custom_target(flutter_assemble DEPENDS
99 | "${FLUTTER_LIBRARY}"
100 | ${FLUTTER_LIBRARY_HEADERS}
101 | ${CPP_WRAPPER_SOURCES_CORE}
102 | ${CPP_WRAPPER_SOURCES_PLUGIN}
103 | ${CPP_WRAPPER_SOURCES_APP}
104 | )
105 |
--------------------------------------------------------------------------------
/example/linux/my_application.cc:
--------------------------------------------------------------------------------
1 | #include "my_application.h"
2 |
3 | #include
4 | #ifdef GDK_WINDOWING_X11
5 | #include
6 | #endif
7 |
8 | #include "flutter/generated_plugin_registrant.h"
9 |
10 | struct _MyApplication {
11 | GtkApplication parent_instance;
12 | char** dart_entrypoint_arguments;
13 | };
14 |
15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
16 |
17 | // Implements GApplication::activate.
18 | static void my_application_activate(GApplication* application) {
19 | MyApplication* self = MY_APPLICATION(application);
20 | GtkWindow* window =
21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
22 |
23 | // Use a header bar when running in GNOME as this is the common style used
24 | // by applications and is the setup most users will be using (e.g. Ubuntu
25 | // desktop).
26 | // If running on X and not using GNOME then just use a traditional title bar
27 | // in case the window manager does more exotic layout, e.g. tiling.
28 | // If running on Wayland assume the header bar will work (may need changing
29 | // if future cases occur).
30 | gboolean use_header_bar = TRUE;
31 | #ifdef GDK_WINDOWING_X11
32 | GdkScreen* screen = gtk_window_get_screen(window);
33 | if (GDK_IS_X11_SCREEN(screen)) {
34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
36 | use_header_bar = FALSE;
37 | }
38 | }
39 | #endif
40 | if (use_header_bar) {
41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
42 | gtk_widget_show(GTK_WIDGET(header_bar));
43 | gtk_header_bar_set_title(header_bar, "example");
44 | gtk_header_bar_set_show_close_button(header_bar, TRUE);
45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
46 | } else {
47 | gtk_window_set_title(window, "example");
48 | }
49 |
50 | gtk_window_set_default_size(window, 1280, 720);
51 | gtk_widget_show(GTK_WIDGET(window));
52 |
53 | g_autoptr(FlDartProject) project = fl_dart_project_new();
54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
55 |
56 | FlView* view = fl_view_new(project);
57 | gtk_widget_show(GTK_WIDGET(view));
58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
59 |
60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view));
61 |
62 | gtk_widget_grab_focus(GTK_WIDGET(view));
63 | }
64 |
65 | // Implements GApplication::local_command_line.
66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
67 | MyApplication* self = MY_APPLICATION(application);
68 | // Strip out the first argument as it is the binary name.
69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
70 |
71 | g_autoptr(GError) error = nullptr;
72 | if (!g_application_register(application, nullptr, &error)) {
73 | g_warning("Failed to register: %s", error->message);
74 | *exit_status = 1;
75 | return TRUE;
76 | }
77 |
78 | g_application_activate(application);
79 | *exit_status = 0;
80 |
81 | return TRUE;
82 | }
83 |
84 | // Implements GObject::dispose.
85 | static void my_application_dispose(GObject* object) {
86 | MyApplication* self = MY_APPLICATION(object);
87 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
88 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
89 | }
90 |
91 | static void my_application_class_init(MyApplicationClass* klass) {
92 | G_APPLICATION_CLASS(klass)->activate = my_application_activate;
93 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
94 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
95 | }
96 |
97 | static void my_application_init(MyApplication* self) {}
98 |
99 | MyApplication* my_application_new() {
100 | return MY_APPLICATION(g_object_new(my_application_get_type(),
101 | "application-id", APPLICATION_ID,
102 | "flags", G_APPLICATION_NON_UNIQUE,
103 | nullptr));
104 | }
105 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: A new Flutter project.
3 | # The following line prevents the package from being accidentally published to
4 | # pub.dev using `flutter pub publish`. This is preferred for private packages.
5 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
6 |
7 | # The following defines the version and build number for your application.
8 | # A version number is three numbers separated by dots, like 1.2.43
9 | # followed by an optional build number separated by a +.
10 | # Both the version and the builder number may be overridden in flutter
11 | # build by specifying --build-name and --build-number, respectively.
12 | # In Android, build-name is used as versionName while build-number used as versionCode.
13 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
14 | # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
15 | # Read more about iOS versioning at
16 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17 | # In Windows, build-name is used as the major, minor, and patch parts
18 | # of the product and file versions while build-number is used as the build suffix.
19 | version: 1.0.0+1
20 |
21 | environment:
22 | sdk: '>=3.0.5 <4.0.0'
23 |
24 | # Dependencies specify other packages that your package needs in order to work.
25 | # To automatically upgrade your package dependencies to the latest versions
26 | # consider running `flutter pub upgrade --major-versions`. Alternatively,
27 | # dependencies can be manually updated by changing the version numbers below to
28 | # the latest version available on pub.dev. To see which dependencies have newer
29 | # versions available, run `flutter pub outdated`.
30 | dependencies:
31 | flutter:
32 | sdk: flutter
33 |
34 |
35 | # The following adds the Cupertino Icons font to your application.
36 | # Use with the CupertinoIcons class for iOS style icons.
37 | cupertino_icons: ^1.0.2
38 | multi_dropdown:
39 | path: ../
40 | go_router: ^14.2.1
41 |
42 | dev_dependencies:
43 | flutter_test:
44 | sdk: flutter
45 |
46 | # The "flutter_lints" package below contains a set of recommended lints to
47 | # encourage good coding practices. The lint set provided by the package is
48 | # activated in the `analysis_options.yaml` file located at the root of your
49 | # package. See that file for information about deactivating specific lint
50 | # rules and activating additional ones.
51 | flutter_lints: ^2.0.0
52 |
53 | # For information on the generic Dart part of this file, see the
54 | # following page: https://dart.dev/tools/pub/pubspec
55 |
56 | # The following section is specific to Flutter packages.
57 | flutter:
58 |
59 | # The following line ensures that the Material Icons font is
60 | # included with your application, so that you can use the icons in
61 | # the material Icons class.
62 | uses-material-design: true
63 |
64 | # To add assets to your application, add an assets section, like this:
65 | # assets:
66 | # - images/a_dot_burr.jpeg
67 | # - images/a_dot_ham.jpeg
68 |
69 | # An image asset can refer to one or more resolution-specific "variants", see
70 | # https://flutter.dev/assets-and-images/#resolution-aware
71 |
72 | # For details regarding adding assets from package dependencies, see
73 | # https://flutter.dev/assets-and-images/#from-packages
74 |
75 | # To add custom fonts to your application, add a fonts section here,
76 | # in this "flutter" section. Each entry in this list should have a
77 | # "family" key with the font family name, and a "fonts" key with a
78 | # list giving the asset and other descriptors for the font. For
79 | # example:
80 | # fonts:
81 | # - family: Schyler
82 | # fonts:
83 | # - asset: fonts/Schyler-Regular.ttf
84 | # - asset: fonts/Schyler-Italic.ttf
85 | # style: italic
86 | # - family: Trajan Pro
87 | # fonts:
88 | # - asset: fonts/TrajanPro.ttf
89 | # - asset: fonts/TrajanPro_Bold.ttf
90 | # weight: 700
91 | #
92 | # For details regarding fonts from package dependencies,
93 | # see https://flutter.dev/custom-fonts/#from-packages
94 |
--------------------------------------------------------------------------------
/example/windows/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Project-level configuration.
2 | cmake_minimum_required(VERSION 3.14)
3 | project(example LANGUAGES CXX)
4 |
5 | # The name of the executable created for the application. Change this to change
6 | # the on-disk name of your application.
7 | set(BINARY_NAME "example")
8 |
9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
10 | # versions of CMake.
11 | cmake_policy(SET CMP0063 NEW)
12 |
13 | # Define build configuration option.
14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
15 | if (IS_MULTICONFIG)
16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
17 | CACHE STRING "" FORCE)
18 | else ()
19 | if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
20 | set(CMAKE_BUILD_TYPE "Debug" CACHE
21 | STRING "Flutter build mode" FORCE)
22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
23 | "Debug" "Profile" "Release")
24 | endif ()
25 | endif ()
26 | # Define settings for the Profile build mode.
27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
31 |
32 | # Use Unicode for all projects.
33 | add_definitions(-DUNICODE -D_UNICODE)
34 |
35 | # Compilation settings that should be applied to most targets.
36 | #
37 | # Be cautious about adding new options here, as plugins use this function by
38 | # default. In most cases, you should add new options to specific targets instead
39 | # of modifying this function.
40 | function(APPLY_STANDARD_SETTINGS TARGET)
41 | target_compile_features(${TARGET} PUBLIC cxx_std_17)
42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
43 | target_compile_options(${TARGET} PRIVATE /EHsc)
44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>")
46 | endfunction()
47 |
48 | # Flutter library and tool build rules.
49 | set(FLUTTER_MANAGED_DIR "flutter")
50 | add_subdirectory(${FLUTTER_MANAGED_DIR})
51 |
52 | # Application build; see runner/CMakeLists.txt.
53 | add_subdirectory("runner")
54 |
55 |
56 | # Generated plugin build rules, which manage building the plugins and adding
57 | # them to the application.
58 | include(flutter/generated_plugins.cmake)
59 |
60 |
61 | # === Installation ===
62 | # Support files are copied into place next to the executable, so that it can
63 | # run in place. This is done instead of making a separate bundle (as on Linux)
64 | # so that building and running from within Visual Studio will work.
65 | set(BUILD_BUNDLE_DIR "$")
66 | # Make the "install" step default, as it's required to run.
67 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
68 | if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
69 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
70 | endif ()
71 |
72 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
73 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
74 |
75 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
76 | COMPONENT Runtime)
77 |
78 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
79 | COMPONENT Runtime)
80 |
81 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
82 | COMPONENT Runtime)
83 |
84 | if (PLUGIN_BUNDLED_LIBRARIES)
85 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
86 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
87 | COMPONENT Runtime)
88 | endif ()
89 |
90 | # Fully re-copy the assets directory on each build to avoid having stale files
91 | # from a previous install.
92 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
93 | install(CODE "
94 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
95 | " COMPONENT Runtime)
96 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
97 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
98 |
99 | # Install the AOT library on non-Debug builds only.
100 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
101 | CONFIGURATIONS Profile;Release
102 | COMPONENT Runtime)
--------------------------------------------------------------------------------
/example/linux/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Project-level configuration.
2 | cmake_minimum_required(VERSION 3.10)
3 | project(runner LANGUAGES CXX)
4 |
5 | # The name of the executable created for the application. Change this to change
6 | # the on-disk name of your application.
7 | set(BINARY_NAME "example")
8 | # The unique GTK application identifier for this application. See:
9 | # https://wiki.gnome.org/HowDoI/ChooseApplicationID
10 | set(APPLICATION_ID "com.oinarendra.multidropdownexample.example")
11 |
12 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
13 | # versions of CMake.
14 | cmake_policy(SET CMP0063 NEW)
15 |
16 | # Load bundled libraries from the lib/ directory relative to the binary.
17 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
18 |
19 | # Root filesystem for cross-building.
20 | if (FLUTTER_TARGET_PLATFORM_SYSROOT)
21 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
22 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
23 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
24 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
25 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
26 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
27 | endif ()
28 |
29 | # Define build configuration options.
30 | if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
31 | set(CMAKE_BUILD_TYPE "Debug" CACHE
32 | STRING "Flutter build mode" FORCE)
33 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
34 | "Debug" "Profile" "Release")
35 | endif ()
36 |
37 | # Compilation settings that should be applied to most targets.
38 | #
39 | # Be cautious about adding new options here, as plugins use this function by
40 | # default. In most cases, you should add new options to specific targets instead
41 | # of modifying this function.
42 | function(APPLY_STANDARD_SETTINGS TARGET)
43 | target_compile_features(${TARGET} PUBLIC cxx_std_14)
44 | target_compile_options(${TARGET} PRIVATE -Wall -Werror)
45 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>")
46 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>")
47 | endfunction()
48 |
49 | # Flutter library and tool build rules.
50 | set(FLUTTER_MANAGED_DIR "flutter")
51 | add_subdirectory(${FLUTTER_MANAGED_DIR})
52 |
53 | # System-level dependencies.
54 | find_package(PkgConfig REQUIRED)
55 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
56 |
57 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
58 |
59 | # Define the application target. To change its name, change BINARY_NAME above,
60 | # not the value here, or `flutter run` will no longer work.
61 | #
62 | # Any new source files that you add to the application should be added here.
63 | add_executable(${BINARY_NAME}
64 | "main.cc"
65 | "my_application.cc"
66 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
67 | )
68 |
69 | # Apply the standard set of build settings. This can be removed for applications
70 | # that need different build settings.
71 | apply_standard_settings(${BINARY_NAME})
72 |
73 | # Add dependency libraries. Add any application-specific dependencies here.
74 | target_link_libraries(${BINARY_NAME} PRIVATE flutter)
75 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
76 |
77 | # Run the Flutter tool portions of the build. This must not be removed.
78 | add_dependencies(${BINARY_NAME} flutter_assemble)
79 |
80 | # Only the install-generated bundle's copy of the executable will launch
81 | # correctly, since the resources must in the right relative locations. To avoid
82 | # people trying to run the unbundled copy, put it in a subdirectory instead of
83 | # the default top-level location.
84 | set_target_properties(${BINARY_NAME}
85 | PROPERTIES
86 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
87 | )
88 |
89 |
90 | # Generated plugin build rules, which manage building the plugins and adding
91 | # them to the application.
92 | include(flutter/generated_plugins.cmake)
93 |
94 |
95 | # === Installation ===
96 | # By default, "installing" just makes a relocatable bundle in the build
97 | # directory.
98 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
99 | if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
100 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
101 | endif ()
102 |
103 | # Start with a clean build bundle directory every time.
104 | install(CODE "
105 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
106 | " COMPONENT Runtime)
107 |
108 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
109 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
110 |
111 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
112 | COMPONENT Runtime)
113 |
114 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
115 | COMPONENT Runtime)
116 |
117 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
118 | COMPONENT Runtime)
119 |
120 | foreach (bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
121 | install(FILES "${bundled_library}"
122 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
123 | COMPONENT Runtime)
124 | endforeach (bundled_library)
125 |
126 | # Fully re-copy the assets directory on each build to avoid having stale files
127 | # from a previous install.
128 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
129 | install(CODE "
130 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
131 | " COMPONENT Runtime)
132 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
133 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
134 |
135 | # Install the AOT library on non-Debug builds only.
136 | if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
137 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
138 | COMPONENT Runtime)
139 | endif ()
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # ChangeLOG
2 |
3 | ## 3.0.1
4 |
5 | - Fixed overlay exception error.
6 | - Fixed Text Direction issue.
7 | - Exposed `OnSearchChange` callback to get the search query.
8 | - Fixed dropdown reset issue when used inside a `ListView`.
9 | - Close dropdown when single select item is selected.
10 |
11 | ## 3.0.0
12 |
13 | ### Breaking Changes
14 |
15 | - Multiple breaking changes have been made to the library to make it more flexible and customizable.
16 | - The library has been completely rewritten to make it more flexible and customizable.
17 | - `MultiSelectDropDown` is now `MultiDropdown`.
18 | - `ValueItem` is now `DropdownItem`. It now supports `disabled` & `selected` properties.
19 | - Added `.future` constructor to `MultiDropdown` to support future options. It now shows a loading indicator when the future is being resolved.
20 | - `.custom` constructor is now removed. You need to handle custom network requests manually by using the `.future` constructor.
21 | - Dropdown now supports `Form Validation`, `Prefix Icon` and some other properties.
22 | - Dropdown now somewhat takes decoration from theme, to make the UI more consistent across the app.
23 | - Refer to the parameters of the `MultiDropdown` widget for more information.
24 |
25 | ## 3.0.0-dev.5
26 |
27 | - `height` property in `DropdownDecoration` is renamed to `maxHeight`.
28 |
29 | ## 3.0.0-dev.4
30 |
31 | - Fixed `search` feature not working issue.
32 | - Fixed `itemBuilder` not working properly.
33 |
34 | ## 3.0.0-dev.3
35 |
36 | - Fixed issue causing `onSelectionChange` callback to not work properly.
37 |
38 | ## 3.0.0-beta.1
39 |
40 | - Added `closeOnBackButton` property to `MultiDropdown` to close the dropdown when the back button is pressed.
41 | - Added `footer` and `header` properties to `DropdownDecoration` to add a custom footer and header to the dropdown.
42 | - When dropdown is opened, now it supports gesture in the background as well. Example: You can now scroll the list behind the dropdown, when the dropdown is open.
43 | - `prefixIcon` in `FieldDecoration` is now a `Widget` instead of an `Icon`.
44 | - Fixed dropdown not opening on web.
45 | - Fixed an issue causing validation to not work properly when using controller to update the dropdown.
46 | - Renamed controller's `.open` method to `.showDropdown` and `.hide` method to `.closeDropdown`.
47 |
48 | ## 3.0.0-dev.2
49 |
50 | - Added `backgroundColor` property to `FieldDecoration` to set the background color of the dropdown field.
51 | - Fixed issue with `onSelectionChange` callback.
52 |
53 | ## 3.0.0-dev.1
54 |
55 | - Multiple breaking changes have been made to the library to make it more flexible and customizable.
56 | - The library has been completely rewritten to make it more flexible and customizable.
57 |
58 | ## Features
59 |
60 | - `MultiSelectDropDown` is now `MultiDropdown`.
61 | - `ValueItem` is now `DropdownItem`. It now supports `disabled` & `selected` properties.
62 | - Added `.future` constructor to `MultiDropdown` to support future options. It now shows a loading indicator when the future is being resolved.
63 | - `.custom` constructor is now removed. You need to handle custom network requests manually by using the `.future` constructor.
64 | - Dropdown now supports `Form Validation`, `Prefix Icon` and some other properties.
65 | - Dropdown now somewhat takes decoration from theme, to make the UI more consistent across the app.
66 |
67 | ## 2.1.5
68 |
69 | - Renamed `NetworkConfig` class to `NetworkRequest`.
70 | - responseParser and responseErrorBuilder are now moved inside the `NetworkRequest` class.
71 | - `NetworkRequest.custom` is now added to support custom network requests.
72 | - Fixed an issue where unnecessary network call was being made when used with networkRequest.
73 | - Updated chip style to support `disabled background color`, `disabled label color`, and `border side`.
74 | - Fixed issue which caused the border-radius of the dropdown to be clipped by options
75 | - Rename `borderRadius` parameter to `fieldBorderRadius`
76 | - DropdwnField now shows a `loading indicator` when the options are being fetched from the network.
77 |
78 | ## 2.1.4
79 |
80 | - Removed `showClearIcon` property from dropdown field. Use clearIcon property to set the clear icon. If clearIcon is null, the clear icon will not be shown.
81 | - Added `singleSelectItemStyle` property to dropdown field. Use this property to set the style of the selected item in single select dropdown.
82 | - Fixed suffixIcon animation issue in dropdown field, also added `animateSuffixIcon` property to enable/disable suffix icon animation.
83 | - Added `optionBuilder` property to dropdown field. Use this property to build custom dropdown options.
84 |
85 | ## 2.1.3
86 |
87 | - Added dropdown background color property, search field background color property, and search field label property.
88 | - Added onDelete callback to dropdown field. This callback is called when option is deleted from the dropdown field using
89 | the delete icon/button in chips.
90 |
91 | ## 2.1.2
92 |
93 | - Fixed dropdown dismiss issue when search is enabled and option is/are selected on web.
94 | - Fixed the issue where the selected options were ignored when the widget is rebuilt.
95 |
96 | ## 2.1.1
97 |
98 | - Added dropdown margin property. Use this property to set the margin between the dropdown field and the dropdown.
99 | - Added dropdownborderradius property. Use this property to set the border radius of the dropdown.
100 | - Fixed controller being used after being disposed.
101 |
102 | ## 2.1.0
103 |
104 | - Added support for search in dropdown options.
105 |
106 | ## 2.0.2
107 |
108 | - Added support for custom suffix icon in dropdown field.
109 | - Added support for custom clear icon in dropdown field.
110 | - Fixed the issue where the dropdown would not follow the dropdown field when the dropdown field is scrolled.
111 | - Updated http dependency to 1.1.0.
112 |
113 | ## 2.0.1
114 |
115 | - Added maxItems property to dropdown field. If max items is set, the dropdown field will not allow more than the specified number of items to be selected.
116 | - Upgraded http dependency to 1.0.0.
117 |
118 | ## 2.0.0
119 |
120 | - Stable release.
121 |
122 | ## 2.0.0-dev.3
123 |
124 | - Fixed issue where selecting an option after passing initial options would not work.
125 |
126 | ## 2.0.0-dev.2
127 |
128 | - Fixed issue where chips were not being cleared when controller not set.
129 |
130 | ## 2.0.0-dev.1
131 |
132 | - Added support for controller.
133 | - Use controller to get/set selected options, disabled options, options, and enabled options.
134 | - Use controller to clear selected options, show/hide dropdown.
135 | - Added support for focusnode, use focusnode to focus/unfocus the dropdown field programmatically.
136 |
137 | ## 1.0.9
138 |
139 | - Added clear button to dropdown field.
140 | - Added support focus on dropdown field.
141 |
142 | ## 1.0.8
143 |
144 | - Updated dropdown to detect available space and show the dropdown above or below the field.
145 |
146 | ## 1.0.7
147 |
148 | - Added custom border radius in dropdown.
149 |
150 | ## 1.0.6
151 |
152 | - Fixed selected option text color not being applied.
153 |
154 | ## 1.0.5
155 |
156 | - Fixed onOptionsSelected callback not being called when deleting the chip item.
157 | - Fixed issue causing overlay exception.
158 |
159 | ## 1.0.4
160 |
161 | - Added support for dropdown field padding, border color, border width, and border radius.
162 | - Fixed onOptionsSelected callback not being called.
163 | - Added toString/JsonSerialization/Equality/Hash methods to ValueItem class.
164 |
165 | ## 1.0.3
166 |
167 | - Added new constructor that supports fetching the data from a URL.
168 |
169 | ## 1.0.2
170 |
171 | - Added example.
172 |
173 | ## 1.0.1
174 |
175 | - Updated screenshots.
176 |
177 | ## 1.0.0
178 |
179 | - Initial release.
180 |
--------------------------------------------------------------------------------
/lib/src/widgets/dropdown.dart:
--------------------------------------------------------------------------------
1 | part of '../multi_dropdown.dart';
2 |
3 | /// Dropdown widget for the multiselect dropdown.
4 | ///
5 | class _Dropdown extends StatelessWidget {
6 | /// Creates a dropdown widget.
7 | const _Dropdown({
8 | required this.decoration,
9 | required this.width,
10 | required this.searchEnabled,
11 | required this.dropdownItemDecoration,
12 | required this.searchDecoration,
13 | required this.maxSelections,
14 | required this.items,
15 | required this.onItemTap,
16 | Key? key,
17 | this.onSearchChange,
18 | this.itemBuilder,
19 | this.itemSeparator,
20 | this.singleSelect = false,
21 | }) : super(key: key);
22 |
23 | /// The decoration of the dropdown.
24 | final DropdownDecoration decoration;
25 |
26 | /// Whether the search field is enabled.
27 | final bool searchEnabled;
28 |
29 | /// The width of the dropdown.
30 | final double width;
31 |
32 | /// The decoration of the dropdown items.
33 | final DropdownItemDecoration dropdownItemDecoration;
34 |
35 | /// Dropdown item builder, if not provided, the default ListTile will be used.
36 | final DropdownItemBuilder? itemBuilder;
37 |
38 | /// The separator between the dropdown items.
39 | final Widget? itemSeparator;
40 |
41 | /// The decoration of the search field.
42 | final SearchFieldDecoration searchDecoration;
43 |
44 | /// The maximum number of selections allowed.
45 | final int maxSelections;
46 |
47 | /// The list of dropdown items.
48 | final List> items;
49 |
50 | /// The callback when an item is tapped.
51 | final ValueChanged> onItemTap;
52 |
53 | /// The callback when the search field value changes.
54 | final ValueChanged? onSearchChange;
55 |
56 | /// Whether the selection is single.
57 | final bool singleSelect;
58 |
59 | int get _selectedCount => items.where((element) => element.selected).length;
60 |
61 | static const Map _webShortcuts =
62 | {
63 | SingleActivator(LogicalKeyboardKey.arrowDown):
64 | DirectionalFocusIntent(TraversalDirection.down),
65 | SingleActivator(LogicalKeyboardKey.arrowUp):
66 | DirectionalFocusIntent(TraversalDirection.up),
67 | };
68 |
69 | @override
70 | Widget build(BuildContext context) {
71 | final theme = Theme.of(context);
72 |
73 | final child = Material(
74 | elevation: decoration.elevation,
75 | borderRadius: decoration.borderRadius,
76 | clipBehavior: Clip.antiAlias,
77 | color: decoration.backgroundColor,
78 | surfaceTintColor: decoration.backgroundColor,
79 | child: Focus(
80 | canRequestFocus: false,
81 | skipTraversal: true,
82 | child: Container(
83 | decoration: BoxDecoration(
84 | borderRadius: decoration.borderRadius,
85 | color: decoration.backgroundColor,
86 | backgroundBlendMode: BlendMode.dstATop,
87 | ),
88 | constraints: BoxConstraints(
89 | maxWidth: width,
90 | maxHeight: decoration.maxHeight,
91 | ),
92 | child: Column(
93 | mainAxisSize: MainAxisSize.min,
94 | crossAxisAlignment: CrossAxisAlignment.stretch,
95 | children: [
96 | if (searchEnabled)
97 | _SearchField(
98 | decoration: searchDecoration,
99 | onChanged: _onSearchChange,
100 | ),
101 | if (decoration.header != null)
102 | Flexible(child: decoration.header!),
103 | Flexible(
104 | child: ListView.separated(
105 | separatorBuilder: (_, __) =>
106 | itemSeparator ?? const SizedBox.shrink(),
107 | shrinkWrap: true,
108 | itemCount: items.length,
109 | itemBuilder: (_, int index) => _buildOption(index, theme),
110 | ),
111 | ),
112 | if (items.isEmpty && searchEnabled)
113 | Padding(
114 | padding: const EdgeInsets.all(12),
115 | child: Text(
116 | 'No items found',
117 | textAlign: TextAlign.center,
118 | style: theme.textTheme.bodyMedium,
119 | ),
120 | ),
121 | if (decoration.footer != null)
122 | Flexible(child: decoration.footer!),
123 | ],
124 | ),
125 | ),
126 | ),
127 | );
128 |
129 | if (kIsWeb || Platform.isMacOS || Platform.isLinux || Platform.isWindows) {
130 | return Shortcuts(shortcuts: _webShortcuts, child: child);
131 | }
132 |
133 | return child;
134 | }
135 |
136 | Widget _buildOption(int index, ThemeData theme) {
137 | final option = items[index];
138 |
139 | if (itemBuilder != null) {
140 | return itemBuilder!(option, index, () => onItemTap(option));
141 | }
142 |
143 | final disabledColor = dropdownItemDecoration.disabledBackgroundColor ??
144 | dropdownItemDecoration.backgroundColor?.withAlpha(100);
145 |
146 | final tileColor = option.disabled
147 | ? disabledColor
148 | : option.selected
149 | ? dropdownItemDecoration.selectedBackgroundColor
150 | : dropdownItemDecoration.backgroundColor;
151 |
152 | final trailing = option.disabled
153 | ? dropdownItemDecoration.disabledIcon
154 | : option.selected
155 | ? dropdownItemDecoration.selectedIcon
156 | : null;
157 |
158 | return Ink(
159 | child: ListTile(
160 | title: Text(option.label),
161 | trailing: trailing,
162 | dense: true,
163 | autofocus: true,
164 | enabled: !option.disabled,
165 | selected: option.selected,
166 | visualDensity: VisualDensity.adaptivePlatformDensity,
167 | focusColor: dropdownItemDecoration.backgroundColor?.withAlpha(100),
168 | selectedColor: dropdownItemDecoration.selectedTextColor ??
169 | theme.colorScheme.onSurface,
170 | textColor:
171 | dropdownItemDecoration.textColor ?? theme.colorScheme.onSurface,
172 | tileColor: tileColor ?? Colors.transparent,
173 | selectedTileColor: dropdownItemDecoration.selectedBackgroundColor ??
174 | Colors.grey.shade200,
175 | onTap: () {
176 | if (option.disabled) return;
177 |
178 | if (singleSelect || !_reachedMaxSelection(option)) {
179 | onItemTap(option);
180 | return;
181 | }
182 | },
183 | ),
184 | );
185 | }
186 |
187 | void _onSearchChange(String value) => onSearchChange?.call(value);
188 |
189 | bool _reachedMaxSelection(DropdownItem option) {
190 | return !option.selected &&
191 | maxSelections > 0 &&
192 | _selectedCount >= maxSelections;
193 | }
194 | }
195 |
196 | class _SearchField extends StatelessWidget {
197 | const _SearchField({
198 | required this.decoration,
199 | required this.onChanged,
200 | });
201 |
202 | final SearchFieldDecoration decoration;
203 |
204 | final ValueChanged onChanged;
205 |
206 | @override
207 | Widget build(BuildContext context) {
208 | return Padding(
209 | padding: const EdgeInsets.all(8),
210 | child: TextField(
211 | decoration: InputDecoration(
212 | isDense: true,
213 | hintText: decoration.hintText,
214 | border: decoration.border,
215 | focusedBorder: decoration.focusedBorder,
216 | suffixIcon: decoration.searchIcon,
217 | ),
218 | onChanged: onChanged,
219 | ),
220 | );
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.1"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.18.0"
44 | cupertino_icons:
45 | dependency: "direct main"
46 | description:
47 | name: cupertino_icons
48 | sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.0.8"
52 | fake_async:
53 | dependency: transitive
54 | description:
55 | name: fake_async
56 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "1.3.1"
60 | flutter:
61 | dependency: "direct main"
62 | description: flutter
63 | source: sdk
64 | version: "0.0.0"
65 | flutter_lints:
66 | dependency: "direct dev"
67 | description:
68 | name: flutter_lints
69 | sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
70 | url: "https://pub.dev"
71 | source: hosted
72 | version: "2.0.3"
73 | flutter_test:
74 | dependency: "direct dev"
75 | description: flutter
76 | source: sdk
77 | version: "0.0.0"
78 | flutter_web_plugins:
79 | dependency: transitive
80 | description: flutter
81 | source: sdk
82 | version: "0.0.0"
83 | go_router:
84 | dependency: "direct main"
85 | description:
86 | name: go_router
87 | sha256: "39dd52168d6c59984454183148dc3a5776960c61083adfc708cc79a7b3ce1ba8"
88 | url: "https://pub.dev"
89 | source: hosted
90 | version: "14.2.1"
91 | leak_tracker:
92 | dependency: transitive
93 | description:
94 | name: leak_tracker
95 | sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
96 | url: "https://pub.dev"
97 | source: hosted
98 | version: "10.0.4"
99 | leak_tracker_flutter_testing:
100 | dependency: transitive
101 | description:
102 | name: leak_tracker_flutter_testing
103 | sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
104 | url: "https://pub.dev"
105 | source: hosted
106 | version: "3.0.3"
107 | leak_tracker_testing:
108 | dependency: transitive
109 | description:
110 | name: leak_tracker_testing
111 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
112 | url: "https://pub.dev"
113 | source: hosted
114 | version: "3.0.1"
115 | lints:
116 | dependency: transitive
117 | description:
118 | name: lints
119 | sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
120 | url: "https://pub.dev"
121 | source: hosted
122 | version: "2.1.1"
123 | logging:
124 | dependency: transitive
125 | description:
126 | name: logging
127 | sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
128 | url: "https://pub.dev"
129 | source: hosted
130 | version: "1.2.0"
131 | matcher:
132 | dependency: transitive
133 | description:
134 | name: matcher
135 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
136 | url: "https://pub.dev"
137 | source: hosted
138 | version: "0.12.16+1"
139 | material_color_utilities:
140 | dependency: transitive
141 | description:
142 | name: material_color_utilities
143 | sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
144 | url: "https://pub.dev"
145 | source: hosted
146 | version: "0.8.0"
147 | meta:
148 | dependency: transitive
149 | description:
150 | name: meta
151 | sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
152 | url: "https://pub.dev"
153 | source: hosted
154 | version: "1.12.0"
155 | multi_dropdown:
156 | dependency: "direct main"
157 | description:
158 | path: ".."
159 | relative: true
160 | source: path
161 | version: "3.0.1"
162 | path:
163 | dependency: transitive
164 | description:
165 | name: path
166 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
167 | url: "https://pub.dev"
168 | source: hosted
169 | version: "1.9.0"
170 | sky_engine:
171 | dependency: transitive
172 | description: flutter
173 | source: sdk
174 | version: "0.0.99"
175 | source_span:
176 | dependency: transitive
177 | description:
178 | name: source_span
179 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
180 | url: "https://pub.dev"
181 | source: hosted
182 | version: "1.10.0"
183 | stack_trace:
184 | dependency: transitive
185 | description:
186 | name: stack_trace
187 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
188 | url: "https://pub.dev"
189 | source: hosted
190 | version: "1.11.1"
191 | stream_channel:
192 | dependency: transitive
193 | description:
194 | name: stream_channel
195 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
196 | url: "https://pub.dev"
197 | source: hosted
198 | version: "2.1.2"
199 | string_scanner:
200 | dependency: transitive
201 | description:
202 | name: string_scanner
203 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
204 | url: "https://pub.dev"
205 | source: hosted
206 | version: "1.2.0"
207 | term_glyph:
208 | dependency: transitive
209 | description:
210 | name: term_glyph
211 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
212 | url: "https://pub.dev"
213 | source: hosted
214 | version: "1.2.1"
215 | test_api:
216 | dependency: transitive
217 | description:
218 | name: test_api
219 | sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
220 | url: "https://pub.dev"
221 | source: hosted
222 | version: "0.7.0"
223 | vector_math:
224 | dependency: transitive
225 | description:
226 | name: vector_math
227 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
228 | url: "https://pub.dev"
229 | source: hosted
230 | version: "2.1.4"
231 | vm_service:
232 | dependency: transitive
233 | description:
234 | name: vm_service
235 | sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
236 | url: "https://pub.dev"
237 | source: hosted
238 | version: "14.2.1"
239 | sdks:
240 | dart: ">=3.3.0 <4.0.0"
241 | flutter: ">=3.18.0-18.0.pre.54"
242 |
--------------------------------------------------------------------------------
/lib/src/controllers/multiselect_controller.dart:
--------------------------------------------------------------------------------
1 | part of '../multi_dropdown.dart';
2 |
3 | /// Controller for the multiselect dropdown.
4 | class MultiSelectController extends ChangeNotifier {
5 | /// a flag to indicate whether the controller is initialized.
6 | bool _initialized = false;
7 |
8 | /// set initialized flag to true.
9 | void _initialize() {
10 | _initialized = true;
11 | }
12 |
13 | List> _items = [];
14 |
15 | List> _filteredItems = [];
16 |
17 | String _searchQuery = '';
18 |
19 | /// Gets the list of dropdown items.
20 | List> get items =>
21 | _searchQuery.isEmpty ? _items : _filteredItems;
22 |
23 | /// Gets the list of selected dropdown items.
24 | List> get selectedItems =>
25 | _items.where((element) => element.selected).toList();
26 |
27 | /// Get the list of selected dropdown item values.
28 | List get _selectedValues => selectedItems.map((e) => e.value).toList();
29 |
30 | /// Gets the list of disabled dropdown items.
31 | List> get disabledItems =>
32 | _items.where((element) => element.disabled).toList();
33 |
34 | bool _open = false;
35 |
36 | /// Gets whether the dropdown is open.
37 | bool get isOpen => _open;
38 |
39 | bool _isDisposed = false;
40 |
41 | /// Gets whether the controller is disposed.
42 | bool get isDisposed => _isDisposed;
43 |
44 | /// on selection changed callback invoker.
45 | OnSelectionChanged? _onSelectionChanged;
46 |
47 | /// on search changed callback invoker.
48 | OnSearchChanged? _onSearchChanged;
49 |
50 | /// sets the list of dropdown items.
51 | /// It replaces the existing list of dropdown items.
52 | void setItems(List> options) {
53 | _items
54 | ..clear()
55 | ..addAll(options);
56 | notifyListeners();
57 | _onSelectionChanged?.call(_selectedValues);
58 | }
59 |
60 | /// Adds a dropdown item to the list of dropdown items.
61 | /// The [index] parameter is optional, and if provided, the item will be inserted at the specified index.
62 | void addItem(DropdownItem option, {int index = -1}) {
63 | if (index == -1) {
64 | _items.add(option);
65 | } else {
66 | _items.insert(index, option);
67 | }
68 | notifyListeners();
69 | _onSelectionChanged?.call(_selectedValues);
70 | }
71 |
72 | /// Adds a list of dropdown items to the list of dropdown items.
73 | void addItems(List> options) {
74 | _items.addAll(options);
75 | notifyListeners();
76 | _onSelectionChanged?.call(_selectedValues);
77 | }
78 |
79 | /// clears all the selected items.
80 | void clearAll() {
81 | _items = _items
82 | .map(
83 | (element) =>
84 | element.selected ? element.copyWith(selected: false) : element,
85 | )
86 | .toList();
87 | notifyListeners();
88 | _onSelectionChanged?.call(_selectedValues);
89 | }
90 |
91 | /// selects all the items.
92 | void selectAll() {
93 | _items = _items
94 | .map(
95 | (element) =>
96 | !element.selected ? element.copyWith(selected: true) : element,
97 | )
98 | .toList();
99 | notifyListeners();
100 | _onSelectionChanged?.call(_selectedValues);
101 | }
102 |
103 | /// select the item at the specified index.
104 | ///
105 | /// The [index] parameter is the index of the item to select.
106 | void selectAtIndex(int index) {
107 | if (index < 0 || index >= _items.length) return;
108 |
109 | final item = _items[index];
110 |
111 | if (item.disabled || item.selected) return;
112 |
113 | selectWhere((element) => element == _items[index]);
114 | }
115 |
116 | /// deselects all the items.
117 | void toggleWhere(bool Function(DropdownItem item) predicate) {
118 | _items = _items
119 | .map(
120 | (element) => predicate(element)
121 | ? element.copyWith(selected: !element.selected)
122 | : element,
123 | )
124 | .toList();
125 | if (_searchQuery.isNotEmpty) {
126 | _filteredItems = _items
127 | .where(
128 | (item) =>
129 | item.label.toLowerCase().contains(_searchQuery.toLowerCase()),
130 | )
131 | .toList();
132 | }
133 | notifyListeners();
134 | _onSelectionChanged?.call(_selectedValues);
135 | }
136 |
137 | /// selects the items that satisfy the predicate.
138 | ///
139 | /// The [predicate] parameter is a function that takes a [DropdownItem] and returns a boolean.
140 | void selectWhere(bool Function(DropdownItem item) predicate) {
141 | _items = _items
142 | .map(
143 | (element) => predicate(element) && !element.selected
144 | ? element.copyWith(selected: true)
145 | : element,
146 | )
147 | .toList();
148 | notifyListeners();
149 | _onSelectionChanged?.call(_selectedValues);
150 | }
151 |
152 | void _toggleOnly(DropdownItem item) {
153 | _items = _items
154 | .map(
155 | (element) => element == item
156 | ? element.copyWith(selected: !element.selected)
157 | : element.copyWith(selected: false),
158 | )
159 | .toList();
160 |
161 | notifyListeners();
162 | _onSelectionChanged?.call(_selectedValues);
163 | }
164 |
165 | /// unselects the items that satisfy the predicate.
166 | ///
167 | /// The [predicate] parameter is a function that takes a [DropdownItem] and returns a boolean.
168 | void unselectWhere(bool Function(DropdownItem item) predicate) {
169 | _items = _items
170 | .map(
171 | (element) => predicate(element) && element.selected
172 | ? element.copyWith(selected: false)
173 | : element,
174 | )
175 | .toList();
176 | notifyListeners();
177 | _onSelectionChanged?.call(_selectedValues);
178 | }
179 |
180 | /// disables the items that satisfy the predicate.
181 | ///
182 | /// The [predicate] parameter is a function that takes a [DropdownItem] and returns a boolean.
183 | void disableWhere(bool Function(DropdownItem item) predicate) {
184 | _items = _items
185 | .map(
186 | (element) => predicate(element) && !element.disabled
187 | ? element.copyWith(disabled: true)
188 | : element,
189 | )
190 | .toList();
191 | notifyListeners();
192 | _onSelectionChanged?.call(_selectedValues);
193 | }
194 |
195 | /// shows the dropdown, if it is not already open.
196 | void openDropdown() {
197 | if (_open) return;
198 |
199 | _open = true;
200 | notifyListeners();
201 | }
202 |
203 | /// hides the dropdown, if it is not already closed.
204 | void closeDropdown() {
205 | if (!_open) return;
206 |
207 | _open = false;
208 | notifyListeners();
209 | }
210 |
211 | // ignore: use_setters_to_change_properties
212 | void _setOnSelectionChange(OnSelectionChanged? onSelectionChanged) {
213 | this._onSelectionChanged = onSelectionChanged;
214 | }
215 |
216 | // ignore: use_setters_to_change_properties
217 | void _setOnSearchChange(OnSearchChanged? onSearchChanged) {
218 | this._onSearchChanged = onSearchChanged;
219 | }
220 |
221 | // sets the search query.
222 | // The [query] parameter is the search query.
223 | void _setSearchQuery(String query) {
224 | _searchQuery = query;
225 | if (_searchQuery.isEmpty) {
226 | _filteredItems = List.from(_items);
227 | } else {
228 | _filteredItems = _items
229 | .where(
230 | (item) =>
231 | item.label.toLowerCase().contains(_searchQuery.toLowerCase()),
232 | )
233 | .toList();
234 | }
235 | _onSearchChanged?.call(query);
236 | notifyListeners();
237 | }
238 |
239 | // clears the search query.
240 | void _clearSearchQuery({bool notify = false}) {
241 | _searchQuery = '';
242 | if (notify) notifyListeners();
243 | }
244 |
245 | @override
246 | void dispose() {
247 | if (_isDisposed) return;
248 | super.dispose();
249 | _isDisposed = true;
250 | }
251 |
252 | @override
253 | String toString() {
254 | return 'MultiSelectController(options: $_items, open: $_open)';
255 | }
256 |
257 | @override
258 | bool operator ==(Object other) {
259 | if (identical(this, other)) return true;
260 |
261 | return other is MultiSelectController &&
262 | listEquals(other._items, _items) &&
263 | other._open == _open;
264 | }
265 |
266 | @override
267 | int get hashCode => _items.hashCode ^ _open.hashCode;
268 | }
269 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:go_router/go_router.dart';
4 | import 'package:multi_dropdown/multi_dropdown.dart';
5 |
6 | void main() {
7 | runApp(const MyApp());
8 | }
9 |
10 | class MyApp extends StatelessWidget {
11 | const MyApp({Key? key}) : super(key: key);
12 |
13 | // This widget is the root of your application.
14 | @override
15 | Widget build(BuildContext context) {
16 | return MaterialApp.router(
17 | title: 'Multiselect dropdown demo',
18 | debugShowCheckedModeBanner: false,
19 | themeMode: ThemeMode.dark,
20 | theme: ThemeData(
21 | primarySwatch: Colors.green,
22 | ),
23 | routerConfig: GoRouter(routes: [
24 | GoRoute(
25 | path: '/',
26 | builder: (context, state) {
27 | return const MyHomePage();
28 | },
29 | ),
30 | ]),
31 | );
32 | }
33 | }
34 |
35 | class MyHomePage extends StatefulWidget {
36 | const MyHomePage({Key? key}) : super(key: key);
37 |
38 | @override
39 | State createState() => _MyHomePageState();
40 | }
41 |
42 | class User {
43 | final String name;
44 | final int id;
45 |
46 | User({required this.name, required this.id});
47 |
48 | @override
49 | String toString() {
50 | return 'User(name: $name, id: $id)';
51 | }
52 | }
53 |
54 | class _MyHomePageState extends State {
55 | final _formKey = GlobalKey();
56 |
57 | final controller = MultiSelectController();
58 |
59 | @override
60 | Widget build(BuildContext context) {
61 | var items = [
62 | DropdownItem(label: 'Nepal', value: User(name: 'Nepal', id: 1)),
63 | DropdownItem(label: 'Australia', value: User(name: 'Australia', id: 6)),
64 | DropdownItem(label: 'India', value: User(name: 'India', id: 2)),
65 | DropdownItem(label: 'China', value: User(name: 'China', id: 3)),
66 | DropdownItem(label: 'USA', value: User(name: 'USA', id: 4)),
67 | DropdownItem(label: 'UK', value: User(name: 'UK', id: 5)),
68 | DropdownItem(label: 'Germany', value: User(name: 'Germany', id: 7)),
69 | DropdownItem(label: 'France', value: User(name: 'France', id: 8)),
70 | ];
71 | return Scaffold(
72 | backgroundColor: Colors.white,
73 | body: SafeArea(
74 | child: Padding(
75 | padding: const EdgeInsets.all(16),
76 | child: SingleChildScrollView(
77 | physics: const AlwaysScrollableScrollPhysics(),
78 | child: SizedBox(
79 | width: double.infinity,
80 | height: MediaQuery.of(context).size.height,
81 | child: Form(
82 | key: _formKey,
83 | child: Column(
84 | crossAxisAlignment: CrossAxisAlignment.start,
85 | mainAxisSize: MainAxisSize.max,
86 | children: [
87 | const SizedBox(
88 | height: 4,
89 | ),
90 | MultiDropdown(
91 | items: items,
92 | controller: controller,
93 | enabled: true,
94 | searchEnabled: true,
95 | chipDecoration: const ChipDecoration(
96 | backgroundColor: Colors.yellow,
97 | wrap: true,
98 | runSpacing: 2,
99 | spacing: 10,
100 | ),
101 | fieldDecoration: FieldDecoration(
102 | hintText: 'Countries',
103 | hintStyle: const TextStyle(color: Colors.black87),
104 | prefixIcon: const Icon(CupertinoIcons.flag),
105 | showClearIcon: false,
106 | border: OutlineInputBorder(
107 | borderRadius: BorderRadius.circular(12),
108 | borderSide: const BorderSide(color: Colors.grey),
109 | ),
110 | focusedBorder: OutlineInputBorder(
111 | borderRadius: BorderRadius.circular(12),
112 | borderSide: const BorderSide(
113 | color: Colors.black87,
114 | ),
115 | ),
116 | ),
117 | dropdownDecoration: const DropdownDecoration(
118 | marginTop: 2,
119 | maxHeight: 500,
120 | header: Padding(
121 | padding: EdgeInsets.all(8),
122 | child: Text(
123 | 'Select countries from the list',
124 | textAlign: TextAlign.start,
125 | style: TextStyle(
126 | fontSize: 16,
127 | fontWeight: FontWeight.bold,
128 | ),
129 | ),
130 | ),
131 | ),
132 | dropdownItemDecoration: DropdownItemDecoration(
133 | selectedIcon:
134 | const Icon(Icons.check_box, color: Colors.green),
135 | disabledIcon:
136 | Icon(Icons.lock, color: Colors.grey.shade300),
137 | ),
138 | validator: (value) {
139 | if (value == null || value.isEmpty) {
140 | return 'Please select a country';
141 | }
142 | return null;
143 | },
144 | onSelectionChange: (selectedItems) {
145 | debugPrint("OnSelectionChange: $selectedItems");
146 | },
147 | ),
148 | const SizedBox(height: 12),
149 | Wrap(
150 | spacing: 8,
151 | children: [
152 | ElevatedButton(
153 | onPressed: () {
154 | if (_formKey.currentState?.validate() ?? false) {
155 | final selectedItems = controller.selectedItems;
156 |
157 | debugPrint(selectedItems.toString());
158 | }
159 | },
160 | child: const Text('Submit'),
161 | ),
162 | ElevatedButton(
163 | onPressed: () {
164 | controller.selectAll();
165 | },
166 | child: const Text('Select All'),
167 | ),
168 | ElevatedButton(
169 | onPressed: () {
170 | controller.clearAll();
171 | },
172 | child: const Text('Unselect All'),
173 | ),
174 | ElevatedButton(
175 | onPressed: () {
176 | controller.addItems([
177 | DropdownItem(
178 | label: 'France',
179 | value: User(name: 'France', id: 8)),
180 | ]);
181 | },
182 | child: const Text('Add Items'),
183 | ),
184 | ElevatedButton(
185 | onPressed: () {
186 | controller.selectWhere((element) =>
187 | element.value.id == 1 ||
188 | element.value.id == 2 ||
189 | element.value.id == 3);
190 | },
191 | child: const Text('Select Where'),
192 | ),
193 | ElevatedButton(
194 | onPressed: () {
195 | controller.selectAtIndex(0);
196 | },
197 | child: const Text('Select At Index'),
198 | ),
199 | ElevatedButton(
200 | onPressed: () {
201 | controller.openDropdown();
202 | },
203 | child: const Text('Open/Close dropdown'),
204 | ),
205 | ],
206 | )
207 | ],
208 | ),
209 | ),
210 | ),
211 | ),
212 | ),
213 | ));
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/example/windows/runner/win32_window.cpp:
--------------------------------------------------------------------------------
1 | #include "win32_window.h"
2 |
3 | #include
4 | #include
5 |
6 | #include "resource.h"
7 |
8 | namespace {
9 |
10 | /// Window attribute that enables dark mode window decorations.
11 | ///
12 | /// Redefined in case the developer's machine has a Windows SDK older than
13 | /// version 10.0.22000.0.
14 | /// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
15 | #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
16 | #define DWMWA_USE_IMMERSIVE_DARK_MODE 20
17 | #endif
18 |
19 | constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
20 |
21 | /// Registry key for app theme preference.
22 | ///
23 | /// A value of 0 indicates apps should use dark mode. A non-zero or missing
24 | /// value indicates apps should use light mode.
25 | constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
26 | L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
27 | constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
28 |
29 | // The number of Win32Window objects that currently exist.
30 | static int g_active_window_count = 0;
31 |
32 | using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
33 |
34 | // Scale helper to convert logical scaler values to physical using passed in
35 | // scale factor
36 | int Scale(int source, double scale_factor) {
37 | return static_cast(source * scale_factor);
38 | }
39 |
40 | // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
41 | // This API is only needed for PerMonitor V1 awareness mode.
42 | void EnableFullDpiSupportIfAvailable(HWND hwnd) {
43 | HMODULE user32_module = LoadLibraryA("User32.dll");
44 | if (!user32_module) {
45 | return;
46 | }
47 | auto enable_non_client_dpi_scaling =
48 | reinterpret_cast(
49 | GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
50 | if (enable_non_client_dpi_scaling != nullptr) {
51 | enable_non_client_dpi_scaling(hwnd);
52 | }
53 | FreeLibrary(user32_module);
54 | }
55 |
56 | } // namespace
57 |
58 | // Manages the Win32Window's window class registration.
59 | class WindowClassRegistrar {
60 | public:
61 | ~WindowClassRegistrar() = default;
62 |
63 | // Returns the singleton registrar instance.
64 | static WindowClassRegistrar* GetInstance() {
65 | if (!instance_) {
66 | instance_ = new WindowClassRegistrar();
67 | }
68 | return instance_;
69 | }
70 |
71 | // Returns the name of the window class, registering the class if it hasn't
72 | // previously been registered.
73 | const wchar_t* GetWindowClass();
74 |
75 | // Unregisters the window class. Should only be called if there are no
76 | // instances of the window.
77 | void UnregisterWindowClass();
78 |
79 | private:
80 | WindowClassRegistrar() = default;
81 |
82 | static WindowClassRegistrar* instance_;
83 |
84 | bool class_registered_ = false;
85 | };
86 |
87 | WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
88 |
89 | const wchar_t* WindowClassRegistrar::GetWindowClass() {
90 | if (!class_registered_) {
91 | WNDCLASS window_class{};
92 | window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
93 | window_class.lpszClassName = kWindowClassName;
94 | window_class.style = CS_HREDRAW | CS_VREDRAW;
95 | window_class.cbClsExtra = 0;
96 | window_class.cbWndExtra = 0;
97 | window_class.hInstance = GetModuleHandle(nullptr);
98 | window_class.hIcon =
99 | LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
100 | window_class.hbrBackground = 0;
101 | window_class.lpszMenuName = nullptr;
102 | window_class.lpfnWndProc = Win32Window::WndProc;
103 | RegisterClass(&window_class);
104 | class_registered_ = true;
105 | }
106 | return kWindowClassName;
107 | }
108 |
109 | void WindowClassRegistrar::UnregisterWindowClass() {
110 | UnregisterClass(kWindowClassName, nullptr);
111 | class_registered_ = false;
112 | }
113 |
114 | Win32Window::Win32Window() {
115 | ++g_active_window_count;
116 | }
117 |
118 | Win32Window::~Win32Window() {
119 | --g_active_window_count;
120 | Destroy();
121 | }
122 |
123 | bool Win32Window::Create(const std::wstring& title,
124 | const Point& origin,
125 | const Size& size) {
126 | Destroy();
127 |
128 | const wchar_t* window_class =
129 | WindowClassRegistrar::GetInstance()->GetWindowClass();
130 |
131 | const POINT target_point = {static_cast(origin.x),
132 | static_cast(origin.y)};
133 | HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
134 | UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
135 | double scale_factor = dpi / 96.0;
136 |
137 | HWND window = CreateWindow(
138 | window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
139 | Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
140 | Scale(size.width, scale_factor), Scale(size.height, scale_factor),
141 | nullptr, nullptr, GetModuleHandle(nullptr), this);
142 |
143 | if (!window) {
144 | return false;
145 | }
146 |
147 | UpdateTheme(window);
148 |
149 | return OnCreate();
150 | }
151 |
152 | bool Win32Window::Show() {
153 | return ShowWindow(window_handle_, SW_SHOWNORMAL);
154 | }
155 |
156 | // static
157 | LRESULT CALLBACK Win32Window::WndProc(HWND const window,
158 | UINT const message,
159 | WPARAM const wparam,
160 | LPARAM const lparam) noexcept {
161 | if (message == WM_NCCREATE) {
162 | auto window_struct = reinterpret_cast(lparam);
163 | SetWindowLongPtr(window, GWLP_USERDATA,
164 | reinterpret_cast(window_struct->lpCreateParams));
165 |
166 | auto that = static_cast(window_struct->lpCreateParams);
167 | EnableFullDpiSupportIfAvailable(window);
168 | that->window_handle_ = window;
169 | } else if (Win32Window* that = GetThisFromHandle(window)) {
170 | return that->MessageHandler(window, message, wparam, lparam);
171 | }
172 |
173 | return DefWindowProc(window, message, wparam, lparam);
174 | }
175 |
176 | LRESULT
177 | Win32Window::MessageHandler(HWND hwnd,
178 | UINT const message,
179 | WPARAM const wparam,
180 | LPARAM const lparam) noexcept {
181 | switch (message) {
182 | case WM_DESTROY:
183 | window_handle_ = nullptr;
184 | Destroy();
185 | if (quit_on_close_) {
186 | PostQuitMessage(0);
187 | }
188 | return 0;
189 |
190 | case WM_DPICHANGED: {
191 | auto newRectSize = reinterpret_cast(lparam);
192 | LONG newWidth = newRectSize->right - newRectSize->left;
193 | LONG newHeight = newRectSize->bottom - newRectSize->top;
194 |
195 | SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
196 | newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
197 |
198 | return 0;
199 | }
200 | case WM_SIZE: {
201 | RECT rect = GetClientArea();
202 | if (child_content_ != nullptr) {
203 | // Size and position the child window.
204 | MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
205 | rect.bottom - rect.top, TRUE);
206 | }
207 | return 0;
208 | }
209 |
210 | case WM_ACTIVATE:
211 | if (child_content_ != nullptr) {
212 | SetFocus(child_content_);
213 | }
214 | return 0;
215 |
216 | case WM_DWMCOLORIZATIONCOLORCHANGED:
217 | UpdateTheme(hwnd);
218 | return 0;
219 | }
220 |
221 | return DefWindowProc(window_handle_, message, wparam, lparam);
222 | }
223 |
224 | void Win32Window::Destroy() {
225 | OnDestroy();
226 |
227 | if (window_handle_) {
228 | DestroyWindow(window_handle_);
229 | window_handle_ = nullptr;
230 | }
231 | if (g_active_window_count == 0) {
232 | WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
233 | }
234 | }
235 |
236 | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
237 | return reinterpret_cast(
238 | GetWindowLongPtr(window, GWLP_USERDATA));
239 | }
240 |
241 | void Win32Window::SetChildContent(HWND content) {
242 | child_content_ = content;
243 | SetParent(content, window_handle_);
244 | RECT frame = GetClientArea();
245 |
246 | MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
247 | frame.bottom - frame.top, true);
248 |
249 | SetFocus(child_content_);
250 | }
251 |
252 | RECT Win32Window::GetClientArea() {
253 | RECT frame;
254 | GetClientRect(window_handle_, &frame);
255 | return frame;
256 | }
257 |
258 | HWND Win32Window::GetHandle() {
259 | return window_handle_;
260 | }
261 |
262 | void Win32Window::SetQuitOnClose(bool quit_on_close) {
263 | quit_on_close_ = quit_on_close;
264 | }
265 |
266 | bool Win32Window::OnCreate() {
267 | // No-op; provided for subclasses.
268 | return true;
269 | }
270 |
271 | void Win32Window::OnDestroy() {
272 | // No-op; provided for subclasses.
273 | }
274 |
275 | void Win32Window::UpdateTheme(HWND const window) {
276 | DWORD light_mode;
277 | DWORD light_mode_size = sizeof(light_mode);
278 | LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
279 | kGetPreferredBrightnessRegValue,
280 | RRF_RT_REG_DWORD, nullptr, &light_mode,
281 | &light_mode_size);
282 |
283 | if (result == ERROR_SUCCESS) {
284 | BOOL enable_dark_mode = light_mode == 0;
285 | DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
286 | &enable_dark_mode, sizeof(enable_dark_mode));
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/lib/src/models/decoration.dart:
--------------------------------------------------------------------------------
1 | part of '../multi_dropdown.dart';
2 |
3 | /// Represents the decoration for the search field in the dropdown.
4 | class SearchFieldDecoration {
5 | /// Creates a new instance of [SearchFieldDecoration].
6 | ///
7 | /// [hintText] is the hint text to display in the search field. The default value is 'Search'.
8 | ///
9 | /// [border] is the border of the search field. The default value is OutlineInputBorder().
10 | ///
11 | /// [focusedBorder] is the border of the search field when it is focused. The default value is OutlineInputBorder().
12 | ///
13 | /// [searchIcon] is the icon to display in the search field. The default value is Icon(Icons.search).
14 | const SearchFieldDecoration({
15 | this.hintText = 'Search',
16 | this.border = const OutlineInputBorder(
17 | borderSide: BorderSide(color: Color(0xFFE0E0E0)),
18 | borderRadius: BorderRadius.all(Radius.circular(12)),
19 | ),
20 | this.focusedBorder = const OutlineInputBorder(
21 | borderSide: BorderSide(color: Colors.grey),
22 | borderRadius: BorderRadius.all(Radius.circular(12)),
23 | ),
24 | this.searchIcon = const Icon(Icons.search),
25 | });
26 |
27 | /// The hint text to display in the search field.
28 | final String hintText;
29 |
30 | /// The border of the search field.
31 | final InputBorder? border;
32 |
33 | /// The border of the search field when it is focused.
34 | final InputBorder? focusedBorder;
35 |
36 | /// The icon to display in the search field.
37 | final Icon searchIcon;
38 | }
39 |
40 | /// Represents the decoration for the dropdown items.
41 | class DropdownItemDecoration {
42 | /// Creates a new instance of [DropdownItemDecoration].
43 | ///
44 | /// [backgroundColor] is the background color of the dropdown item. The default value is white.
45 | ///
46 | /// [disabledBackgroundColor] is the background color of the disabled dropdown item. The default value is grey.
47 | ///
48 | /// [selectedBackgroundColor] is the background color of the selected dropdown item. The default value is blue.
49 | ///
50 | /// [selectedTextColor] is the text color of the selected dropdown item. The default value is white.
51 | ///
52 | /// [textColor] is the text color of the dropdown item. The default value is black.
53 | ///
54 | /// [disabledTextColor] is the text color of the disabled dropdown item. The default value is black.
55 | ///
56 | /// [selectedIcon] is the icon to display for the selected dropdown item. The default value is Icon(Icons.check).
57 | ///
58 | /// [disabledIcon] is the icon to display for the disabled dropdown item.
59 | const DropdownItemDecoration({
60 | this.backgroundColor,
61 | this.disabledBackgroundColor,
62 | this.selectedBackgroundColor,
63 | this.selectedTextColor,
64 | this.textColor,
65 | this.disabledTextColor,
66 | this.selectedIcon = const Icon(Icons.check),
67 | this.disabledIcon,
68 | });
69 |
70 | /// The background color of the dropdown item.
71 | final Color? backgroundColor;
72 |
73 | /// The background color of the disabled dropdown item.
74 | final Color? disabledBackgroundColor;
75 |
76 | /// The background color of the selected dropdown item.
77 | final Color? selectedBackgroundColor;
78 |
79 | /// The text color of the selected dropdown item.
80 | final Color? selectedTextColor;
81 |
82 | /// The text color of the dropdown item.
83 | final Color? textColor;
84 |
85 | /// The text color of the disabled dropdown item.
86 | final Color? disabledTextColor;
87 |
88 | /// The icon to display for the selected dropdown item.
89 | final Icon? selectedIcon;
90 |
91 | /// The icon to display for the disabled dropdown item.
92 | final Icon? disabledIcon;
93 | }
94 |
95 | /// Represents the decoration for the dropdown.
96 | class DropdownDecoration {
97 | /// Creates a new instance of [DropdownDecoration].
98 | ///
99 | /// [backgroundColor] is the background color of the dropdown. The default value is white.
100 | ///
101 | /// [elevation] is the elevation of the dropdown. The default value is 1.
102 | ///
103 | /// [maxHeight] is the height of the dropdown. The default value is 300.
104 | ///
105 | /// [marginTop] is the margin top of the dropdown. The default value is 0.
106 | ///
107 | /// [borderRadius] is the border radius of the dropdown. The default value is 12.
108 | ///
109 |
110 | const DropdownDecoration({
111 | this.backgroundColor = Colors.white,
112 | this.elevation = 1,
113 | this.maxHeight = 400,
114 | this.marginTop = 0,
115 | this.borderRadius = const BorderRadius.all(Radius.circular(12)),
116 | this.footer,
117 | this.header,
118 | });
119 |
120 | /// The background color of the dropdown.
121 | final Color backgroundColor;
122 |
123 | /// The elevation of the dropdown.
124 | final double elevation;
125 |
126 | /// The maximum height of the dropdown.
127 | final double maxHeight;
128 |
129 | /// The border radius of the dropdown.
130 | final BorderRadius borderRadius;
131 |
132 | /// the margin top of the dropdown
133 | final double marginTop;
134 |
135 | /// The custom footer widget to display at the bottom of the dropdown.
136 | final Widget? footer;
137 |
138 | /// The custom header widget to display at the top of the dropdown.
139 | final Widget? header;
140 | }
141 |
142 | /// Represents the decoration for the dropdown field.
143 | class FieldDecoration {
144 | /// Creates a new instance of [FieldDecoration].
145 | ///
146 | /// [labelText] is the label text to display above the dropdown field.
147 | ///
148 | /// [hintText] is the hint text to display in the dropdown field. The default value is 'Select'.
149 | ///
150 | /// [border] is the border of the dropdown field.
151 | ///
152 | /// [focusedBorder] is the border of the dropdown field when it is focused.
153 | ///
154 | /// [disabledBorder] is the border of the dropdown field when it is disabled.
155 | ///
156 | /// [errorBorder] is the border of the dropdown field when there is an error.
157 | ///
158 | /// [suffixIcon] is the icon to display at the end of dropdown field. The default value is Icon(Icons.arrow_drop_down).
159 | ///
160 | /// [prefixIcon] is the icon to display at the start of dropdown field.
161 | ///
162 | /// [labelStyle] is the style of the label text.
163 | ///
164 | /// [hintStyle] is the style of the hint text.
165 | ///
166 | /// [borderRadius] is the border radius of the dropdown field. The default value is 12.
167 | ///
168 | /// [animateSuffixIcon] is whether to animate the suffix icon or not when dropdown is opened/closed. The default value is true.
169 | ///
170 | /// [suffixIcon] is the icon to display at the end of dropdown field.
171 | ///
172 | /// [prefixIcon] is the icon to display at the start of dropdown field.
173 | ///
174 | /// [padding] is the padding around the dropdown field.
175 | ///
176 | /// [backgroundColor] is the background color of the dropdown field.
177 | const FieldDecoration({
178 | this.labelText,
179 | this.hintText = 'Select',
180 | this.border,
181 | this.focusedBorder,
182 | this.disabledBorder,
183 | this.errorBorder,
184 | this.suffixIcon = const Icon(Icons.arrow_drop_down),
185 | this.prefixIcon,
186 | this.labelStyle,
187 | this.borderRadius = 12,
188 | this.hintStyle,
189 | this.animateSuffixIcon = true,
190 | this.padding = const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
191 | this.backgroundColor,
192 | this.showClearIcon = true,
193 | });
194 |
195 | /// The label text to display above the dropdown field.
196 | final String? labelText;
197 |
198 | /// The hint text to display in the dropdown field.
199 | final String? hintText;
200 |
201 | /// The border of the dropdown field.
202 | final InputBorder? border;
203 |
204 | /// The border of the dropdown field when it is focused.
205 | final InputBorder? focusedBorder;
206 |
207 | /// The border of the dropdown field when it is disabled.
208 | final InputBorder? disabledBorder;
209 |
210 | /// The border of the dropdown field when there is an error.
211 | final InputBorder? errorBorder;
212 |
213 | /// The icon to display at the end of dropdown field.
214 | final Widget? suffixIcon;
215 |
216 | /// The icon to display at the start of dropdown field.
217 | final Widget? prefixIcon;
218 |
219 | /// The style of the label text.
220 | final TextStyle? labelStyle;
221 |
222 | /// The style of the hint text.
223 | final TextStyle? hintStyle;
224 |
225 | /// The border radius of the dropdown field.
226 | final double borderRadius;
227 |
228 | /// animate the icon or not
229 | final bool animateSuffixIcon;
230 |
231 | /// padding around the dropdown field
232 | final EdgeInsets? padding;
233 |
234 | /// background color of the dropdown field
235 | final Color? backgroundColor;
236 |
237 | /// show clear icon or not in the dropdown field
238 | final bool showClearIcon;
239 | }
240 |
241 | /// Configuration class for customizing the appearance of chips in the multi-select dropdown.
242 | class ChipDecoration {
243 | /// Creates a new instance of [ChipDecoration].
244 | ///
245 | /// [deleteIcon] is the icon to display for deleting a chip.
246 | ///
247 | /// [backgroundColor] is the background color of the chip.
248 | ///
249 | /// [labelStyle] is the style of the chip label.
250 | ///
251 | /// [padding] is the padding around the chip.
252 | ///
253 | /// [border] is the border of the chip.
254 | ///
255 | /// [spacing] is the spacing between chips.
256 | ///
257 | /// [runSpacing] is the spacing between chip rows (when the chips wrap).
258 | ///
259 | /// [borderRadius] is the border radius of the chip.
260 | ///
261 | /// [wrap] is whether to wrap or not.
262 | const ChipDecoration({
263 | this.deleteIcon,
264 | this.backgroundColor = const Color(0xFFE0E0E0),
265 | this.padding = const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
266 | this.border = const Border(),
267 | this.spacing = 8,
268 | this.runSpacing = 12,
269 | this.labelStyle,
270 | this.borderRadius = const BorderRadius.all(Radius.circular(12)),
271 | this.wrap = true,
272 | });
273 |
274 | /// The icon to display for deleting a chip.
275 | final Icon? deleteIcon;
276 |
277 | /// The background color of the chip.
278 | final Color? backgroundColor;
279 |
280 | /// The style of the chip label.
281 | final TextStyle? labelStyle;
282 |
283 | /// The padding around the chip.
284 | final EdgeInsets padding;
285 |
286 | /// The border of the chip.
287 | final BoxBorder border;
288 |
289 | /// The spacing between chips.
290 | final double spacing;
291 |
292 | /// The spacing between chip rows (when the chips wrap).
293 | final double runSpacing;
294 |
295 | /// The border radius of the chip.
296 | final BorderRadiusGeometry borderRadius;
297 |
298 | /// Whether to wrap or not
299 | ///
300 | /// If true, the chips will wrap to the next line when they reach the end of the row.
301 | /// If false, the chips will not wrap and will be displayed in a single line, scrolling horizontally if necessary.
302 | final bool wrap;
303 | }
304 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MultiSelect Dropdown
2 |
3 | [](https://pub.dev/packages/multi_dropdown)
4 | [](https://github.com/oi-narendra/multiselect-dropdown/blob/main/LICENSE)
5 | [](https://img.shields.io/github/issues/oi-narendra/multiselect-dropdown)
6 | [](https://pub.dev/packages/very_good_analysis)
7 | [](https://flutter.dev/)
8 | [](https://dart.dev/)
9 |
10 | The MultiSelect Dropdown for Flutter is a powerful and customizable widget that empowers you to effortlessly manage and search through multiple items in a dropdown list. Customize the dropdown with your own style, and use the controller to programmatically control the dropdown.
11 |
12 | ## Breaking Changes in v3.0.0
13 |
14 | - The `MultiSelectDropDown` widget has been renamed to `MultiDropdown`, which now supports `FormValidation`.
15 | - The `MultiSelectController` methods have been updated/renamed.
16 | - The `ValueItem` class has replaced the `DropdownItem` class.
17 | - The `.network` constructor has been removed and has been replaced with the `future` constructor, which accepts a future callback to fetch the data from the server. Use it to handle future your own way.
18 | - `onOptionsSelected` has been replaced with `onSelectionChange`. The `onSelectionChange` callback is called whenever the selection changes in the dropdown, whether it is selected or deselected.
19 | - A lot of parameters have been renamed and updated. Please check the documentation for the updated parameters.
20 |
21 | ## Links
22 |
23 | [Preview](#preview) | [Controller](#controller) | [Parameters](#parameters)
24 |
25 | ## Preview
26 |
27 | [
](screenshot_1.png)
28 | [
](screenshot_2.png)
29 | [
](screenshot_3.png)
30 | [
](screenshot_4.png)
31 |
32 | ## Controller
33 |
34 | You can use the controller to programmatically select/unselect items, clear the selection, and get the selected items, set disabled items, show/hide the dropdown. It is still in beta, will be stable in the next release.
35 |
36 | ```dart
37 | final MultiSelectController _controller = MultiSelectController();
38 |
39 | _controller.clearAll(); /// Clear all selected items
40 |
41 | _controller.selectWhere(bool Function(DropdownItem) predicate); /// Select items based on a predicate
42 |
43 | _controller.setItems(List> options); /// Set items of the dropdown
44 |
45 | _controller.addItem(DropdownItem option); /// Add item to dropdown
46 |
47 | _controller.addItems(List> options); /// Add items to dropdown
48 |
49 | _controller.disableWhere(bool Function(DropdownItem) predicate); /// Disable items based on a predicate
50 |
51 | _controller.selectAll(); /// Select all items
52 |
53 | _controller.selectAtIndex(int index); /// Select item at index
54 |
55 | _controller.selectWhere(bool Function(DropdownItem) predicate); /// Select items based on a predicate
56 |
57 | _controller.deselectWhere(bool Function(DropdownItem) predicate); /// Deselect items based on a predicate
58 |
59 | _controller.items; /// Get all items
60 |
61 | _controller.selectedItems; /// Get selected items
62 |
63 | _controller.disabledItems; /// Get disabled items
64 |
65 | _controller.openDropdown(); /// Show the dropdown
66 |
67 | _controller.closeDropdown(); /// Hide the dropdown if it is open
68 |
69 | ```
70 |
71 | ## Parameters
72 |
73 | ## MultiDropdown
74 |
75 | | Parameter | Type | Description | Default |
76 | | ---------------------- | --------------------------------------------------------- | ------------------------------------------ | ------------------------- |
77 | | items | List> | The list of dropdown items. | Required |
78 | | singleSelect | bool | The selection type of the dropdown. | false |
79 | | chipDecoration | ChipDecoration | The configuration for the chips. | ChipDecoration() |
80 | | fieldDecoration | FieldDecoration | The decoration of the field. | FieldDecoration() |
81 | | dropdownDecoration | DropdownDecoration | The decoration of the dropdown. | DropdownDecoration() |
82 | | searchDecoration | SearchFieldDecoration | The decoration of the search field. | SearchFieldDecoration() |
83 | | dropdownItemDecoration | DropdownItemDecoration | The decoration of the dropdown items. | DropdownItemDecoration() |
84 | | itemBuilder | DropdownItemBuilder? | The builder for the dropdown items. | null |
85 | | selectedItemBuilder | SelectedItemBuilder? | The builder for the selected items. | null |
86 | | itemSeparator | Widget? | The separator between the dropdown items. | null |
87 | | validator | String? Function(List>? selectedOptions)? | The validator for the dropdown. | null |
88 | | autovalidateMode | AutovalidateMode | The autovalidate mode for the dropdown. | AutovalidateMode.disabled |
89 | | controller | MultiSelectController? | The controller for the dropdown. | null |
90 | | maxSelections | int | The maximum number of selections allowed. | 0 |
91 | | enabled | bool | Whether the dropdown is enabled. | true |
92 | | searchEnabled | bool | Whether the search field is enabled. | false |
93 | | focusNode | FocusNode? | The focus node for the dropdown. | null |
94 | | future | FutureRequest? | The future request for the dropdown items. | null |
95 | | onSelectionChange | OnSelectionChanged? | The callback when the item is changed. | null |
96 | | closeOnBackButton | bool | Closes the dropdown on back button | false |
97 | | onSearchChange | ValueChanged? | The callback when the search text changes. | null |
98 |
99 | ## DropdownItem
100 |
101 | | Parameter | Type | Description | Default |
102 | | --------- | ------ | ------------------------------------------------ | -------- |
103 | | label | String | The label of the dropdown item. | Required |
104 | | value | T | The value associated with the dropdown item. | Required |
105 | | disabled | bool | Indicates whether the dropdown item is disabled. | false |
106 | | selected | bool | Indicates whether the dropdown item is selected. | false |
107 |
108 | ## ChipDecoration
109 |
110 | | Parameter | Type | Description | Default |
111 | | --------------- | -------------------- | ---------------------------------------------------- | ------------------------- |
112 | | deleteIcon | Icon | The icon to display for deleting a chip. | Icon(Icons.close) |
113 | | backgroundColor | Color | The background color of the chip. | Colors.blue |
114 | | labelStyle | TextStyle | The style of the chip label. | TextStyle() |
115 | | padding | EdgeInsets | The padding around the chip. | EdgeInsets.all(8.0) |
116 | | border | BoxBorder | The border of the chip. | Border() |
117 | | spacing | double | The spacing between chips. | 8.0 |
118 | | runSpacing | double | The spacing between chip rows (when the chips wrap). | 8.0 |
119 | | borderRadius | BorderRadiusGeometry | The border radius of the chip. | BorderRadius.circular(12) |
120 | | wrap | bool | Whether to wrap chips or scroll them. | true |
121 |
122 | ## FieldDecoration
123 |
124 | | Parameter | Type | Description | Default |
125 | | ----------------- | ------------ | -------------------------------------------------------- | --------------------------- |
126 | | labelText | String? | The label text to display above the dropdown field. | null |
127 | | hintText | String? | The hint text to display in the dropdown field. | null |
128 | | border | InputBorder? | The border of the dropdown field. | null |
129 | | focusedBorder | InputBorder? | The border of the dropdown field when it is focused. | null |
130 | | disabledBorder | InputBorder? | The border of the dropdown field when it is disabled. | null |
131 | | errorBorder | InputBorder? | The border of the dropdown field when there is an error. | null |
132 | | suffixIcon | Widget? | The icon to display at the end of the dropdown field. | Icon(Icons.arrow_drop_down) |
133 | | prefixIcon | Widget? | The icon to display at the start of the dropdown field. | null |
134 | | labelStyle | TextStyle? | The style of the label text. | null |
135 | | hintStyle | TextStyle? | The style of the hint text. | null |
136 | | borderRadius | double | The border radius of the dropdown field. | 8.0 |
137 | | animateSuffixIcon | bool | Animate the icon or not. | true |
138 | | padding | EdgeInsets? | Padding around the dropdown field. | null |
139 | | showClearIcon | bool | Show the clear icon or not. | true |
140 |
141 | ## DropdownDecoration
142 |
143 | | Parameter | Type | Description | Default |
144 | | --------------- | ------------ | ------------------------------------- | --------------------------- |
145 | | backgroundColor | Color | The background color of the dropdown. | Colors.white |
146 | | elevation | double | The elevation of the dropdown. | 1.0 |
147 | | maxHeight | double | The max height of the dropdown. | 400.0 |
148 | | borderRadius | BorderRadius | The border radius of the dropdown. | BorderRadius.circular(12.0) |
149 | | marginTop | double | The margin top of the dropdown. | 0.0 |
150 | | header | Widget? | The header of the dropdown. | null |
151 | | footer | Widget? | The footer of the dropdown. | null |
152 |
153 | ## SearchFieldDecoration
154 |
155 | | Parameter | Type | Description | Default |
156 | | ------------- | ------------ | -------------------------------------------------- | ------------------ |
157 | | hintText | String | The hint text to display in the search field. | 'Search' |
158 | | border | InputBorder? | The border of the search field. | null |
159 | | focusedBorder | InputBorder? | The border of the search field when it is focused. | null |
160 | | searchIcon | Icon | The icon to display in the search field. | Icon(Icons.search) |
161 |
162 | ## DropdownItemDecoration
163 |
164 | | Parameter | Type | Description | Default |
165 | | ----------------------- | ----- | --------------------------------------------------- | ------- |
166 | | backgroundColor | Color | The background color of the dropdown item. | null |
167 | | disabledBackgroundColor | Color | The background color of the disabled dropdown item. | null |
168 | | selectedBackgroundColor | Color | The background color of the selected dropdown item. | null |
169 | | selectedTextColor | Color | The text color of the selected dropdown item. | null |
170 | | textColor | Color | The text color of the dropdown item. | null |
171 | | disabledTextColor | Color | The text color of the disabled dropdown item. | null |
172 | | selectedIcon | Icon | The icon to display for the selected dropdown item. | null |
173 | | disabledIcon | Icon | The icon to display for the disabled dropdown item. | null |
174 |
--------------------------------------------------------------------------------