diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ec133a7..80abd99 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,7 @@ jobs:
flutter analyze . example
- name: Build (Linux)
run: |
- sudo apt-get install clang cmake ninja-build pkg-config libgtk-3-dev
+ sudo apt-get update -y && sudo apt-get install clang cmake ninja-build pkg-config libgtk-3-dev
flutter config --enable-linux-desktop
cd example
flutter create --platforms=linux .
@@ -55,4 +55,4 @@ jobs:
flutter create --platforms=windows .
flutter doctor
flutter build windows
- if: matrix.os == 'windows-latest'
\ No newline at end of file
+ if: matrix.os == 'windows-latest'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2bb6f3f..0857e40 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,21 @@
+# Changelog
+
## 1.0.0
### **BREAKING**
- `AdwHeaderBar.minimal` is now `AdwHeaderBar.custom`
- Remove `label` parameter from `AdwTextField`
+- `ViewSwitcherStyle` is now `ViewSwitcherPolicy`
+- `ViewSwitcherStyle.desktop` and `ViewSwitcherStyle.mobile` are also renamed to `ViewSwitcherPolicy.wide` and `ViewSwitcherPolicy.narrow`
### **Changes to widgets**
+**ComboRow**
+- Dropdown is now scrollable if too many elements are there
+
+**Flap**
+- Renamed `flapController` to `controller`
+- Moved most of the things into `FlapStyle` class to simplify its usage in `AdwScaffold`
+
**HeaderBar**
- Now the `AdwHeaderBar` is not dependent on any package, `windowDecor` object is now optional
- Add `isTransparent` parameter => Makes `AdwHeaderBar`'s background and border color
@@ -12,6 +23,11 @@
**Popover**
- Revisit popup menu by using `popover_gtk` package (popover package with fade transition) (#35)
+**TextField**
+- Add `autofocus` parameter
+- Add `prefixIcon` parameter
+- Add `onSubmitted` parameter
+
**ViewSwitcher**
- Add `badge` in `AdwViewSwitcher`
@@ -59,4 +75,4 @@
- Replace trailing with end
- Replace center with title
-For older Changelog visit: https://pub.dev/packages/gtk/changelog
+Older CHANGELOG can be found [here](https://pub.dev/packages/gtk/changelog)
diff --git a/README.md b/README.md
index 9562147..9538c07 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ Libadwaita's widgets for Flutter. Following Gnome HIG and available on all platf
## Usage
- This only provides widgets, for theming you should consider [adwaita](https://pub.dev/packages/adwaita) or [yaru](https://github.com/ubuntu/yaru.dart) package.
-- If you want custom titlebar then you can follow the steps for that on [`bitsdojo_window`](https://pub.dev/packages/bitsdojo_window) package.
+- If you want custom titlebar then you can follow the steps for that on [`libadwaita_bitsdojo`](https://pub.dev/packages/libadwaita_bitsdojo) package.
- Here is the list of widgets imported from libadwaita library : [widgets.dart](https://github.com/gtk-flutter/libadwaita/blob/main/lib/src/widgets/widgets.dart).
See the example app in the `example` folder for more info.
@@ -36,14 +36,14 @@ If you want to use default adwaita style window icons or icons using window_deco
| Widget | Docs |
| ------ | ---- |
| `AdwHeaderBar` | Default HeaderBar |
-| `AdwHeaderBar.bitsdojo` | HeaderBar to be used with [`bitsdojo`](#bitsdojo_window) package |
+| `AdwHeaderBar.bitsdojo` | HeaderBar to be used with [`bitsdojo`](#libadwaita_bitsdojo) package |
| `AdwHeaderBar.nativeshell` | HeaderBar to be used with [`nativeshell`](#nativeshell) package |
If you want to have a custom icon for window button then you have to use any one of the following HeaderBar's:
| Widget | Docs |
| ------ | ---- |
| `AdwHeaderBar.custom` | HeaderBar with custom icon |
-| `AdwHeaderBar.customBitsdojo` | HeaderBar to be used with [`bitsdojo`](#bitsdojo_window) package with custom icon |
+| `AdwHeaderBar.customBitsdojo` | HeaderBar to be used with [`bitsdojo`](#libadwaita_bitsdojo) package with custom icon |
| `AdwHeaderBar.customNativeshell` | HeaderBar to be used with [`nativeshell`](#nativeshell) package with custom icon |
## Relavant Links
@@ -62,14 +62,14 @@ For theming
#### [**`adwaita_icons`**](https://pub.dev/packages/adwaita_icons)
For Adwaita Icons
-#### [**`bitsdojo_window`**](https://pub.dev/packages/bitsdojo_window)
+#### [**`libadwaita_bitsdojo`**](https://pub.dev/packages/libadwaita_bitsdojo)
Can be used with
- `AdwHeaderBar.bitsdojo`
- `AdwHeaderBar.customBitsdojo`
Example:
```dart
-import 'package:bitsdojo_window/bitsdojo_window.dart';
+import 'package:libadwaita_bitsdojo/libadwaita_bitsdojo.dart';
AdwHeaderBar.bitsdojo(
...
@@ -78,6 +78,20 @@ AdwHeaderBar.bitsdojo(
)
```
+#### [**`libadwaita_searchbar`**](https://pub.dev/packages/libadwaita_searchbar)
+Example:
+```dart
+import 'package:libadwaita_searchbar/libadwaita_searchbar.dart';
+
+bool searchedTerm = '';
+
+AdwSearchBar(
+ suggestions: const ['Hi', 'Hello'],
+ onSubmitted: (str) => setState(() => searchedTerm = str),
+ controller: const TextEditingController(),
+)
+```
+
#### [**`nativeshell`**](https://pub.dev/packages/nativeshell )
Can be used with
- `AdwHeaderBar.nativeshell`
diff --git a/assets/icons/close.svg b/assets/icons/close.svg
index 93f90dc..95d0d83 100644
--- a/assets/icons/close.svg
+++ b/assets/icons/close.svg
@@ -1,27 +1,5 @@
-
-
-
diff --git a/assets/icons/maximize.svg b/assets/icons/maximize.svg
index e000ad3..79b4615 100644
--- a/assets/icons/maximize.svg
+++ b/assets/icons/maximize.svg
@@ -1,30 +1,5 @@
-
-
-
-
-
-
- image/svg+xml
-
- Gnome Symbolic Icon Theme
-
-
-
-
-
-
- Gnome Symbolic Icon Theme
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
\ No newline at end of file
+
diff --git a/assets/icons/minimize.svg b/assets/icons/minimize.svg
index 94f9b5f..7600084 100644
--- a/assets/icons/minimize.svg
+++ b/assets/icons/minimize.svg
@@ -1,30 +1,5 @@
-
-
-
-
-
-
- image/svg+xml
-
- Gnome Symbolic Icon Theme
-
-
-
-
-
-
- Gnome Symbolic Icon Theme
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
\ No newline at end of file
+
diff --git a/example/example.md b/example/example.md
new file mode 100644
index 0000000..bbaafbe
--- /dev/null
+++ b/example/example.md
@@ -0,0 +1,180 @@
+# Examples for libadwaita flutter package
+
+## Demo App
+[Here]('https://github.com/gtk-flutter/libadwaita/tree/main/example') is a demo app made with libadwaita package.
+
+## Minimal [`libadwaita_bitsdojo`](https://pub.dev/packages/libadwaita_bitsdojo) usage
+```yaml
+#pubspec.yaml
+dependencies:
+ adwaita:
+ libadwaita:
+ libadwaita_bitsdojo:
+```
+
+```dart
+// main.dart
+
+import 'package:adwaita/adwaita.dart';
+import 'package:flutter/material.dart';
+import 'package:libadwaita/libadwaita.dart';
+import 'package:libadwaita_bitsdojo/libadwaita_bitsdojo.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ debugShowCheckedModeBanner: false,
+ theme: AdwaitaThemeData.light(),
+ darkTheme: AdwaitaThemeData.dark(),
+ home: MyHomePage(),
+ );
+ }
+}
+
+class MyHomePage extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return AdwScaffold(
+ headerbar: (_) => AdwHeaderBar.bitsdojo(
+ appWindow: appWindow,
+ start: const [
+ AdwHeaderButton(
+ icon: Icon(Icons.nightlight_round, size: 15),
+ ),
+ ],
+ title: const Text('Bitsdojo Window'),
+ ),
+ body: const Center(
+ child: Text('Welcome to Bitsdojo Window Example!'),
+ ),
+ );
+ }
+}
+```
+
+## Minimal [`nativeshell`](https://pub.dev/packages/nativeshell) usage
+```yaml
+#pubspec.yaml
+dependencies:
+ adwaita:
+ libadwaita:
+ nativeshell:
+```
+
+```dart
+// main.dart
+
+import 'package:adwaita/adwaita.dart';
+import 'package:flutter/material.dart';
+import 'package:libadwaita/libadwaita.dart';
+import 'package:nativeshell/nativeshell.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ debugShowCheckedModeBanner: false,
+ theme: AdwaitaThemeData.light(),
+ darkTheme: AdwaitaThemeData.dark(),
+ home: WindowWidget(
+ onCreateState: (dynamic _) {
+ WindowState? state;
+ return state ??= MainWindowState();
+ },
+ ),
+ );
+ }
+}
+
+class MainWindowState extends WindowState {
+ @override
+ Future initializeWindow(Size contentSize) async {
+ await window.setStyle(WindowStyle(frame: WindowFrame.noTitle));
+ await window.show();
+ }
+
+ @override
+ WindowSizingMode get windowSizingMode =>
+ WindowSizingMode.atLeastIntrinsicSize;
+
+ @override
+ Widget build(BuildContext context) {
+ return WindowLayoutProbe(
+ child: AdwScaffold(
+ headerbar: (_) => AdwHeaderBar.nativeshell(
+ window: window,
+ start: const [
+ AdwHeaderButton(
+ icon: Icon(Icons.nightlight_round, size: 15),
+ ),
+ ],
+ title: const Text('Nativeshell'),
+ ),
+ body: const Center(
+ child: Text('Welcome to NativeShell Example!'),
+ ),
+ ),
+ );
+ }
+}
+```
+
+## Minimal [`window_decorations`](https://pub.dev/packages/window_decorations) usage
+```yaml
+#pubspec.yaml
+dependencies:
+ adwaita:
+ libadwaita:
+ window_decorations:
+```
+
+```dart
+// main.dart
+
+import 'package:adwaita/adwaita.dart';
+import 'package:flutter/material.dart';
+import 'package:libadwaita/libadwaita.dart';
+import 'package:window_decorations/window_decorations.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ debugShowCheckedModeBanner: false,
+ theme: AdwaitaThemeData.light(),
+ darkTheme: AdwaitaThemeData.dark(),
+ home: MyHomePage(),
+ );
+ }
+}
+
+class MyHomePage extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return AdwScaffold(
+ headerbar: (_) => AdwHeaderBar(
+ windowDecor: windowDecor,
+ onClose: () {},
+ onMaximize: () {},
+ onMinimize: () {},
+ start: const [
+ AdwHeaderButton(
+ icon: Icon(Icons.nightlight_round, size: 15),
+ ),
+ ],
+ title: const Text('Window Decorations'),
+ ),
+ body: const Center(
+ child: Text('Welcome to Window Decorations Example!'),
+ ),
+ );
+ }
+}
+```
diff --git a/example/lib/flap/flap_home_page.dart b/example/lib/flap/flap_home_page.dart
index 5d327c1..eaf7b2a 100644
--- a/example/lib/flap/flap_home_page.dart
+++ b/example/lib/flap/flap_home_page.dart
@@ -1,6 +1,6 @@
-import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/material.dart';
import 'package:libadwaita/libadwaita.dart';
+import 'package:libadwaita_bitsdojo/libadwaita_bitsdojo.dart';
class FlapHomePage extends StatefulWidget {
const FlapHomePage({Key? key, required this.themeNotifier}) : super(key: key);
@@ -20,6 +20,7 @@ class _FlapHomePageState extends State {
FlapPosition flapPosition = FlapPosition.start;
FoldPolicy foldPolicy = FoldPolicy.auto;
bool locked = false;
+ int selectionIndex = 0;
@override
void initState() {
@@ -45,157 +46,129 @@ class _FlapHomePageState extends State {
@override
Widget build(BuildContext context) {
- return Column(
- children: [
- AdwHeaderBar.bitsdojo(
- appWindow: appWindow,
- start: [
- Builder(
- builder: (context) {
- return AdwHeaderButton(
- icon: const Icon(Icons.view_sidebar, size: 15),
- isActive: _flapController.isOpen,
- onPressed: () => _flapController.toggle(),
- );
- },
- ),
- AdwHeaderButton(
- icon: const Icon(Icons.nightlight_round, size: 15),
- onPressed: changeTheme,
- ),
- ],
- title: const Text('AdwFlap Demo'),
- ),
- Expanded(
- child: AdwScaffold(
- flapController: _flapController,
- drawer: Drawer(
- child: AdwSidebar(
- currentIndex: _currentIndex,
- children: const [
- AdwSidebarItem(
- label: 'Folding',
- ),
- AdwSidebarItem(
- label: 'Layout',
- ),
- AdwSidebarItem(
- label: 'Interaction',
- )
- ],
- onSelected: (index) {
- setState(() {
- _currentIndex = index;
- Navigator.of(context).pop();
- });
- },
- ),
- ),
- body: AdwFlap(
- locked: locked,
- flapController: _flapController,
- flapPosition: flapPosition,
- foldPolicy: foldPolicy,
- flap: AdwSidebar(
- currentIndex: _currentIndex,
- children: const [
- AdwSidebarItem(
- label: 'Folding',
- ),
- AdwSidebarItem(
- label: 'Layout',
- ),
- AdwSidebarItem(
- label: 'Interaction',
- )
- ],
- onSelected: (index) {
- setState(() {
- _currentIndex = index;
- });
- },
- ),
- child: AdwViewStack(
- index: _currentIndex,
- children: [
- AdwClamp.scrollable(
- child: AdwPreferencesGroup(
- children: [
- const AdwComboRow(
- title: 'Fold Policy',
- choices: ['auto', 'always', 'never'],
- ),
- AdwActionRow(
- title: 'Locked',
- subtitle: """
+ return AdwScaffold(
+ flapController: _flapController,
+ headerbar: (_) => AdwHeaderBar.bitsdojo(
+ appWindow: appWindow,
+ start: [
+ Builder(
+ builder: (context) {
+ return AdwHeaderButton(
+ icon: const Icon(Icons.view_sidebar, size: 15),
+ isActive: _flapController.isOpen,
+ onPressed: () => _flapController.toggle(),
+ );
+ },
+ ),
+ AdwHeaderButton(
+ icon: const Icon(Icons.nightlight_round, size: 15),
+ onPressed: changeTheme,
+ ),
+ ],
+ title: const Text('AdwFlap Demo'),
+ ),
+ flap: (isDrawer) => AdwSidebar(
+ currentIndex: _currentIndex,
+ isDrawer: isDrawer,
+ children: const [
+ AdwSidebarItem(
+ label: 'Folding',
+ ),
+ AdwSidebarItem(
+ label: 'Layout',
+ ),
+ AdwSidebarItem(
+ label: 'Interaction',
+ )
+ ],
+ onSelected: (index) => setState(() => _currentIndex = index),
+ ),
+ flapStyle: FlapStyle(
+ locked: locked,
+ flapPosition: flapPosition,
+ foldPolicy: FoldPolicy.values[selectionIndex],
+ ),
+ body: AdwViewStack(
+ index: _currentIndex,
+ children: [
+ AdwClamp.scrollable(
+ child: AdwPreferencesGroup(
+ children: [
+ AdwComboRow(
+ title: 'Fold Policy',
+ selectedIndex: selectionIndex,
+ onSelected: (val) => setState(() => selectionIndex = val),
+ choices: FoldPolicy.values.map((e) => e.name).toList(),
+ ),
+ AdwActionRow(
+ title: 'Locked',
+ subtitle: """
Sidebar visibility doesn't change when fold state changes""",
- end: AdwSwitch(
- value: locked,
- onChanged: (val) {
- locked = val;
- setState(() {});
- },
- ),
- )
- ],
- ),
+ end: AdwSwitch(
+ value: locked,
+ onChanged: (val) {
+ locked = val;
+ setState(() {});
+ },
),
- AdwClamp.scrollable(
- child: AdwPreferencesGroup(
- children: [
- AdwActionRow(
- title: 'Flap position',
- end: AdwToggleButton(
- isSelected: [
- flapPosition.index == 0,
- flapPosition.index == 1
- ],
- onPressed: (val) => setState(() {
- if (val == 0) {
- flapPosition = FlapPosition.start;
- } else {
- flapPosition = FlapPosition.end;
- }
- }),
- children: const [
- Text('Start'),
- Text('End'),
- ],
- ),
- ),
- const AdwActionRow(
- title: 'Transition type',
- end: Text('Over'),
- )
- ],
- ),
+ )
+ ],
+ ),
+ ),
+ AdwClamp.scrollable(
+ child: AdwPreferencesGroup(
+ children: [
+ AdwActionRow(
+ title: 'Flap position',
+ end: AdwToggleButton(
+ isSelected: [
+ flapPosition.index == 0,
+ flapPosition.index == 1
+ ],
+ onPressed: (val) => setState(() {
+ if (val == 0) {
+ flapPosition = FlapPosition.start;
+ } else {
+ flapPosition = FlapPosition.end;
+ }
+ }),
+ children: const [
+ Text('Start'),
+ Text('End'),
+ ],
),
- AdwClamp.scrollable(
- child: AdwPreferencesGroup(
- children: [
- AdwActionRow(
- title: 'Modal',
- subtitle: '''
+ ),
+ AdwComboRow(
+ title: 'Transition type',
+ selectedIndex: 0,
+ onSelected: (val) {},
+ choices: const ['Over', 'Under', 'Slide'],
+ ),
+ ],
+ ),
+ ),
+ AdwClamp.scrollable(
+ child: AdwPreferencesGroup(
+ children: [
+ AdwActionRow(
+ title: 'Modal',
+ subtitle: '''
Clicking outside the sidebar or pressing Esc will close it when folded''',
- end: AdwSwitch(value: true, onChanged: (val) {}),
- ),
- AdwActionRow(
- title: 'Swipe to Open',
- end: AdwSwitch(value: true, onChanged: (val) {}),
- ),
- AdwActionRow(
- title: 'Swipe to Close',
- end: AdwSwitch(value: true, onChanged: (val) {}),
- ),
- ],
- ),
- ),
- ],
- ),
+ end: AdwSwitch(value: true, onChanged: (val) {}),
+ ),
+ AdwActionRow(
+ title: 'Swipe to Open',
+ end: AdwSwitch(value: true, onChanged: (val) {}),
+ ),
+ AdwActionRow(
+ title: 'Swipe to Close',
+ end: AdwSwitch(value: true, onChanged: (val) {}),
+ ),
+ ],
),
),
- ),
- ],
+ ],
+ ),
);
}
}
diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart
index 59afa0b..002f06a 100644
--- a/example/lib/home_page.dart
+++ b/example/lib/home_page.dart
@@ -1,4 +1,3 @@
-import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:example/pages/avatar_page.dart';
import 'package:example/pages/counter_page.dart';
import 'package:example/pages/flap_page.dart';
@@ -7,8 +6,12 @@ import 'package:example/pages/settings_page.dart';
import 'package:example/pages/style_classes_page.dart';
import 'package:example/pages/view_switcher_page.dart';
import 'package:example/pages/welcome.dart';
+
import 'package:flutter/material.dart';
+
import 'package:libadwaita/libadwaita.dart';
+import 'package:libadwaita_bitsdojo/libadwaita_bitsdojo.dart';
+
import 'package:url_launcher/url_launcher.dart';
class MyHomePage extends StatefulWidget {
@@ -60,194 +63,139 @@ class _MyHomePageState extends State {
'Polo': 'pablojimpas',
};
- return Column(
- children: [
- AdwHeaderBar.bitsdojo(
- appWindow: appWindow,
- start: [
- Builder(
- builder: (context) {
- return AdwHeaderButton(
- icon: const Icon(Icons.view_sidebar, size: 15),
- isActive: _flapController.isOpen,
+ return AdwScaffold(
+ flapController: _flapController,
+ headerbar: (_) => AdwHeaderBar.bitsdojo(
+ appWindow: appWindow,
+ start: [
+ AdwHeaderButton(
+ icon: const Icon(Icons.view_sidebar_outlined, size: 19),
+ isActive: _flapController.isOpen,
+ onPressed: () => _flapController.toggle(),
+ ),
+ AdwHeaderButton(
+ icon: const Icon(Icons.nightlight_round, size: 15),
+ onPressed: changeTheme,
+ ),
+ ],
+ title: const Text('Libadwaita Demo'),
+ end: [
+ AdwPopupMenu(
+ body: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ AdwButton.flat(
onPressed: () {
- _flapController.toggle();
+ counter.value = 0;
+ Navigator.of(context).pop();
},
- );
- },
- ),
- AdwHeaderButton(
- icon: const Icon(Icons.nightlight_round, size: 15),
- onPressed: changeTheme,
- ),
- ],
- title: const Text('Libadwaita Demo'),
- end: [
- AdwPopupMenu(
- body: Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: [
- AdwButton.flat(
- onPressed: () {
- counter.value = 0;
- Navigator.of(context).pop();
- },
- padding: AdwButton.defaultButtonPadding.copyWith(
- top: 10,
- bottom: 10,
- ),
- child: const Text(
- 'Reset Counter',
- style: TextStyle(fontSize: 15),
- ),
- ),
- const Divider(),
- AdwButton.flat(
- padding: AdwButton.defaultButtonPadding.copyWith(
- top: 10,
- bottom: 10,
- ),
- child: const Text(
- 'Preferences',
- style: TextStyle(fontSize: 15),
- ),
- ),
- AdwButton.flat(
- padding: AdwButton.defaultButtonPadding.copyWith(
- top: 10,
- bottom: 10,
- ),
- onPressed: () => showDialog(
- context: context,
- builder: (ctx) => AdwAboutWindow(
- issueTrackerLink:
- 'https://github.com/gtk-flutter/libadwaita/issues',
- appIcon: Image.asset('assets/logo.png'),
- credits: [
- AdwPreferencesGroup.credits(
- title: 'Developers',
- children: developers.entries
- .map(
- (e) => AdwActionRow(
- title: e.key,
- onActivated: () =>
- launch('https://github.com/${e.value}'),
- ),
- )
- .toList(),
- ),
- ],
- copyright: 'Copyright 2021-2022 Gtk-Flutter Developers',
- license: const Text(
- 'GNU LGPL-3.0, This program comes with no warranty.',
+ padding: AdwButton.defaultButtonPadding.copyWith(
+ top: 10,
+ bottom: 10,
+ ),
+ child: const Text(
+ 'Reset Counter',
+ style: TextStyle(fontSize: 15),
+ ),
+ ),
+ const Divider(),
+ AdwButton.flat(
+ padding: AdwButton.defaultButtonPadding.copyWith(
+ top: 10,
+ bottom: 10,
+ ),
+ child: const Text(
+ 'Preferences',
+ style: TextStyle(fontSize: 15),
+ ),
+ ),
+ AdwButton.flat(
+ padding: AdwButton.defaultButtonPadding.copyWith(
+ top: 10,
+ bottom: 10,
+ ),
+ onPressed: () => showDialog(
+ context: context,
+ builder: (ctx) => AdwAboutWindow(
+ issueTrackerLink:
+ 'https://github.com/gtk-flutter/libadwaita/issues',
+ appIcon: Image.asset('assets/logo.png'),
+ credits: [
+ AdwPreferencesGroup.credits(
+ title: 'Developers',
+ children: developers.entries
+ .map(
+ (e) => AdwActionRow(
+ title: e.key,
+ onActivated: () =>
+ launch('https://github.com/${e.value}'),
+ ),
+ )
+ .toList(),
),
+ ],
+ copyright: 'Copyright 2021-2022 Gtk-Flutter Developers',
+ license: const Text(
+ 'GNU LGPL-3.0, This program comes with no warranty.',
),
),
- child: const Text(
- 'About this Demo',
- style: TextStyle(fontSize: 15),
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- Expanded(
- child: AdwScaffold(
- flapController: _flapController,
- drawer: Drawer(
- child: AdwSidebar(
- currentIndex: _currentIndex,
- children: const [
- AdwSidebarItem(
- label: 'Welcome',
- ),
- AdwSidebarItem(
- label: 'Counter',
- ),
- AdwSidebarItem(
- label: 'Lists',
),
- AdwSidebarItem(
- label: 'Avatar',
+ child: const Text(
+ 'About this Demo',
+ style: TextStyle(fontSize: 15),
),
- AdwSidebarItem(
- label: 'Flap',
- ),
- AdwSidebarItem(
- label: 'View Switcher',
- ),
- AdwSidebarItem(
- label: 'Settings',
- ),
- AdwSidebarItem(
- label: 'Style Classes',
- )
- ],
- onSelected: (index) {
- setState(() {
- _currentIndex = index;
- Navigator.of(context).pop();
- });
- },
- ),
- ),
- body: AdwFlap(
- flapController: _flapController,
- flap: AdwSidebar(
- currentIndex: _currentIndex,
- children: const [
- AdwSidebarItem(
- label: 'Welcome',
- ),
- AdwSidebarItem(
- label: 'Counter',
- ),
- AdwSidebarItem(
- label: 'Lists',
- ),
- AdwSidebarItem(
- label: 'Avatar',
- ),
- AdwSidebarItem(
- label: 'Flap',
- ),
- AdwSidebarItem(
- label: 'View Switcher',
- ),
- AdwSidebarItem(
- label: 'Settings',
- ),
- AdwSidebarItem(
- label: 'Style Classes',
- )
- ],
- onSelected: (index) {
- setState(() {
- _currentIndex = index;
- });
- },
- ),
- child: AdwViewStack(
- animationDuration: const Duration(milliseconds: 100),
- index: _currentIndex,
- children: [
- const WelcomePage(),
- CounterPage(counter: counter),
- const ListsPage(),
- const AvatarPage(),
- const FlapPage(),
- const ViewSwitcherPage(),
- const SettingsPage(),
- const StyleClassesPage(),
- ],
- ),
+ ),
+ ],
),
),
- ),
- ],
+ ],
+ ),
+ flap: (isDrawer) => AdwSidebar(
+ currentIndex: _currentIndex,
+ isDrawer: isDrawer,
+ children: const [
+ AdwSidebarItem(
+ label: 'Welcome',
+ ),
+ AdwSidebarItem(
+ label: 'Counter',
+ ),
+ AdwSidebarItem(
+ label: 'Lists',
+ ),
+ AdwSidebarItem(
+ label: 'Avatar',
+ ),
+ AdwSidebarItem(
+ label: 'Flap',
+ ),
+ AdwSidebarItem(
+ label: 'View Switcher',
+ ),
+ AdwSidebarItem(
+ label: 'Settings',
+ ),
+ AdwSidebarItem(
+ label: 'Style Classes',
+ )
+ ],
+ onSelected: (index) => setState(() => _currentIndex = index),
+ ),
+ body: AdwViewStack(
+ animationDuration: const Duration(milliseconds: 100),
+ index: _currentIndex,
+ children: [
+ const WelcomePage(),
+ CounterPage(counter: counter),
+ const ListsPage(),
+ const AvatarPage(),
+ const FlapPage(),
+ const ViewSwitcherPage(),
+ const SettingsPage(),
+ const StyleClassesPage(),
+ ],
+ ),
);
}
}
diff --git a/example/lib/pages/counter_page.dart b/example/lib/pages/counter_page.dart
index 041e529..c7ca347 100644
--- a/example/lib/pages/counter_page.dart
+++ b/example/lib/pages/counter_page.dart
@@ -1,3 +1,4 @@
+import 'package:example/pages/run_demo_screen.dart';
import 'package:flutter/material.dart';
import 'package:libadwaita/libadwaita.dart';
@@ -15,28 +16,19 @@ class _CounterPageState extends State {
@override
Widget build(BuildContext context) {
- return Center(
- child: AdwClamp.scrollable(
- child: ValueListenableBuilder(
- valueListenable: widget.counter,
- builder: (_, value, child) {
- return Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- const Text('You have pushed the add button this many times:'),
- Text(
- '$value',
- style: Theme.of(context).textTheme.headline4,
- ),
- AdwButton.pill(
- onPressed: _incrementCounter,
- child: const Text('Add'),
- ),
- ],
- );
- },
- ),
- ),
+ return ValueListenableBuilder(
+ valueListenable: widget.counter,
+ builder: (context, val, _) {
+ return DemoScreen(
+ title: 'Counter Example',
+ description: 'You have pushed the add button this many times:',
+ secondDescription: '$val',
+ footer: AdwButton.pill(
+ onPressed: _incrementCounter,
+ child: const Text('Add'),
+ ),
+ );
+ },
);
}
}
diff --git a/example/lib/pages/flap_page.dart b/example/lib/pages/flap_page.dart
index 976d0f3..34af964 100644
--- a/example/lib/pages/flap_page.dart
+++ b/example/lib/pages/flap_page.dart
@@ -1,40 +1,16 @@
-import 'dart:convert';
-
-import 'package:desktop_multi_window/desktop_multi_window.dart';
+import 'package:example/pages/run_demo_screen.dart';
import 'package:flutter/material.dart';
-import 'package:libadwaita/libadwaita.dart';
class FlapPage extends StatelessWidget {
const FlapPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
- return Center(
- child: AdwClamp.scrollable(
- child: Column(
- children: [
- Text(
- 'Flap',
- style: Theme.of(context).textTheme.headline6,
- ),
- const SizedBox(height: 10),
- const Text(
- 'A widget showing a flap next or above the content.',
- ),
- const SizedBox(height: 16),
- AdwButton.pill(
- onPressed: () async => await DesktopMultiWindow.createWindow(
- jsonEncode({'name': 'flap'}),
- )
- ..setFrame(Offset.zero & const Size(1280, 720))
- ..center()
- ..setTitle('Flap Example')
- ..show(),
- child: const Text('Run the demo'),
- ),
- ],
- ),
- ),
+ return DemoScreen.runDemo(
+ icon: Icons.view_sidebar_rounded,
+ title: 'Flap',
+ description: 'A widget showing a flap next or above the content.',
+ nextPageViewName: 'flap',
);
}
}
diff --git a/example/lib/pages/lists_page.dart b/example/lib/pages/lists_page.dart
index 095d7a6..7b877bc 100644
--- a/example/lib/pages/lists_page.dart
+++ b/example/lib/pages/lists_page.dart
@@ -1,3 +1,4 @@
+import 'package:example/pages/run_demo_screen.dart';
import 'package:flutter/material.dart';
import 'package:libadwaita/libadwaita.dart';
@@ -7,24 +8,18 @@ class ListsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final switchVal = ValueNotifier(false);
- return AdwClamp.scrollable(
- child: Column(
+ const choices = ['Test', 'Second', 'Third and a long name'];
+ final selectionIndex = ValueNotifier(0);
+
+ return DemoScreen(
+ image: const Icon(
+ Icons.list_rounded,
+ size: 150,
+ ),
+ title: 'Lists',
+ description: 'Rows and helpers for GtkListBox.',
+ footer: Column(
children: [
- const Icon(
- Icons.list_rounded,
- size: 150,
- ),
- Text(
- 'Lists',
- style: Theme.of(context)
- .textTheme
- .headline5
- ?.copyWith(fontWeight: FontWeight.bold),
- ),
- const Text('Rows and helpers for GtkListBox.'),
- const SizedBox(
- height: 10,
- ),
AdwPreferencesGroup(
children: [
const AdwActionRow(
@@ -41,11 +36,18 @@ class ListsPage extends StatelessWidget {
)
],
),
- const AdwPreferencesGroup(
+ AdwPreferencesGroup(
children: [
- AdwComboRow(
- choices: ['Test', 'Second', 'Third and a long name'],
- title: 'Combo row',
+ ValueListenableBuilder(
+ valueListenable: selectionIndex,
+ builder: (context, val, _) {
+ return AdwComboRow(
+ choices: choices,
+ title: 'Combo row',
+ selectedIndex: val,
+ onSelected: (val) => selectionIndex.value = val,
+ );
+ },
)
],
),
diff --git a/example/lib/pages/run_demo_screen.dart b/example/lib/pages/run_demo_screen.dart
new file mode 100644
index 0000000..3289e39
--- /dev/null
+++ b/example/lib/pages/run_demo_screen.dart
@@ -0,0 +1,80 @@
+// ignore_for_file: unawaited_futures
+
+import 'dart:convert';
+
+import 'package:desktop_multi_window/desktop_multi_window.dart';
+import 'package:flutter/material.dart';
+import 'package:libadwaita/libadwaita.dart';
+
+class DemoScreen extends StatelessWidget {
+ const DemoScreen({
+ Key? key,
+ required this.title,
+ required this.description,
+ this.secondDescription,
+ this.image,
+ this.footer,
+ }) : super(key: key);
+
+ DemoScreen.runDemo({
+ Key? key,
+ required this.title,
+ required this.description,
+ this.secondDescription,
+ required IconData icon,
+ required String nextPageViewName,
+ }) : image = Icon(
+ icon,
+ size: 130,
+ ),
+ footer = AdwButton.pill(
+ onPressed: () async => await DesktopMultiWindow.createWindow(
+ jsonEncode({'name': nextPageViewName}),
+ )
+ ..setFrame(Offset.zero & const Size(1280, 720))
+ ..center()
+ ..setTitle('$title Example')
+ ..show(),
+ child: const Text('Run the demo'),
+ ),
+ super(key: key);
+
+ final String title;
+ final String description;
+ final String? secondDescription;
+ final Widget? image;
+ final Widget? footer;
+
+ @override
+ Widget build(BuildContext context) {
+ return Center(
+ child: AdwClamp.scrollable(
+ child: Column(
+ children: [
+ if (image != null) ...[
+ image!,
+ const SizedBox(height: 30),
+ ],
+ Text(
+ title,
+ style: Theme.of(context).textTheme.headline1,
+ ),
+ const SizedBox(height: 15),
+ Text(description),
+ if (secondDescription != null) ...[
+ const SizedBox(height: 20),
+ Text(
+ secondDescription!,
+ style: Theme.of(context).textTheme.headline2,
+ ),
+ ],
+ if (footer != null) ...[
+ SizedBox(height: secondDescription != null ? 20 : 40),
+ footer!,
+ ],
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/example/lib/pages/style_classes_page.dart b/example/lib/pages/style_classes_page.dart
index 72ebdd7..f7f7b54 100644
--- a/example/lib/pages/style_classes_page.dart
+++ b/example/lib/pages/style_classes_page.dart
@@ -29,7 +29,7 @@ class StyleClassesPage extends StatelessWidget {
AdwButton(
opaque: true,
margin: const EdgeInsets.symmetric(vertical: 4),
- backgroundColor: AdwColors.blue.backgroundColor,
+ backgroundColor: AdwDefaultColors.blue,
textStyle: const TextStyle(color: Colors.white),
child: const Text('Suggested'),
),
diff --git a/example/lib/pages/view_switcher_page.dart b/example/lib/pages/view_switcher_page.dart
index 4a8b18c..a76c2f6 100644
--- a/example/lib/pages/view_switcher_page.dart
+++ b/example/lib/pages/view_switcher_page.dart
@@ -1,40 +1,16 @@
-import 'dart:convert';
-
-import 'package:desktop_multi_window/desktop_multi_window.dart';
+import 'package:example/pages/run_demo_screen.dart';
import 'package:flutter/material.dart';
-import 'package:libadwaita/libadwaita.dart';
class ViewSwitcherPage extends StatelessWidget {
const ViewSwitcherPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
- return Center(
- child: AdwClamp.scrollable(
- child: Column(
- children: [
- Text(
- 'View Switcher',
- style: Theme.of(context).textTheme.headline6,
- ),
- const SizedBox(height: 10),
- const Text(
- "Widgets to switch the window's view.",
- ),
- const SizedBox(height: 16),
- AdwButton.pill(
- onPressed: () async => await DesktopMultiWindow.createWindow(
- jsonEncode({'name': 'views'}),
- )
- ..setFrame(Offset.zero & const Size(1280, 720))
- ..center()
- ..setTitle('ViewSwitcher Example')
- ..show(),
- child: const Text('Run the demo'),
- ),
- ],
- ),
- ),
+ return DemoScreen.runDemo(
+ title: 'View Switcher',
+ description: "Widgets to switch the window's view.",
+ icon: Icons.table_chart,
+ nextPageViewName: 'views',
);
}
}
diff --git a/example/lib/pages/welcome.dart b/example/lib/pages/welcome.dart
index ccc8bbf..569c209 100644
--- a/example/lib/pages/welcome.dart
+++ b/example/lib/pages/welcome.dart
@@ -1,3 +1,4 @@
+import 'package:example/pages/run_demo_screen.dart';
import 'package:flutter/material.dart';
class WelcomePage extends StatelessWidget {
@@ -5,31 +6,13 @@ class WelcomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
- return Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- const Image(
- image: AssetImage('assets/logo.png'),
- height: 150,
- ),
- Text(
- 'Welcome to Adwaita flutter Demo.',
- style: Theme.of(context)
- .textTheme
- .headline5
- ?.copyWith(fontWeight: FontWeight.bold),
- ),
- const Text(
- 'This is a tour of the features this library has to offer.',
- ),
- ]
- .map(
- (e) => Padding(
- padding: const EdgeInsets.symmetric(vertical: 10),
- child: e,
- ),
- )
- .toList(),
+ return const DemoScreen(
+ image: Image(
+ image: AssetImage('assets/logo.png'),
+ height: 130,
+ ),
+ title: 'Welcome to Adwaita flutter Demo.',
+ description: 'This is a tour of the features this library has to offer.',
);
}
}
diff --git a/example/lib/view_switcher/view_switcher_home_page.dart b/example/lib/view_switcher/view_switcher_home_page.dart
index 3ca950e..817555d 100644
--- a/example/lib/view_switcher/view_switcher_home_page.dart
+++ b/example/lib/view_switcher/view_switcher_home_page.dart
@@ -1,6 +1,6 @@
-import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/material.dart';
import 'package:libadwaita/libadwaita.dart';
+import 'package:libadwaita_bitsdojo/libadwaita_bitsdojo.dart';
class ViewSwitcherHomePage extends StatefulWidget {
const ViewSwitcherHomePage({Key? key}) : super(key: key);
@@ -16,60 +16,53 @@ class _ViewSwitcherHomePageState extends State {
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: index,
- builder: (context, int value, child) {
- return Column(
- children: [
- AdwHeaderBar.bitsdojo(
- appWindow: appWindow,
- title: AdwViewSwitcher(
- tabs: const [
- ViewSwitcherData(
- title: 'World',
- icon: Icons.public,
- ),
- ViewSwitcherData(
- title: 'Alarm',
- icon: Icons.alarm,
- ),
- ViewSwitcherData(
- title: 'Stopwatch',
- icon: Icons.stop,
- badge: '9',
- ),
- ViewSwitcherData(
- title: 'Timer',
- icon: Icons.timer,
- badge: '1',
- ),
- ],
- onViewChanged: (idx) => index.value = idx,
- currentIndex: value,
- ),
+ builder: (context, int value, child) => AdwScaffold(
+ headerbar: (viewSwitcher) => AdwHeaderBar.bitsdojo(
+ appWindow: appWindow,
+ title: viewSwitcher,
+ ),
+ viewSwitcher: AdwViewSwitcher(
+ tabs: const [
+ ViewSwitcherData(
+ title: 'World',
+ icon: Icons.public,
),
- Expanded(
- child: AdwScaffold(
- body: AdwViewStack(
- index: value,
- children: const [
- Center(
- child: Text('World'),
- ),
- Center(
- child: Text('Alarm'),
- ),
- Center(
- child: Text('Stopwatch'),
- ),
- Center(
- child: Text('Timer'),
- ),
- ],
- ),
- ),
+ ViewSwitcherData(
+ title: 'Alarm',
+ icon: Icons.alarm,
+ ),
+ ViewSwitcherData(
+ title: 'Stopwatch',
+ icon: Icons.stop,
+ badge: '9',
+ ),
+ ViewSwitcherData(
+ title: 'Timer',
+ icon: Icons.timer,
+ badge: '1',
+ ),
+ ],
+ onViewChanged: (idx) => index.value = idx,
+ currentIndex: value,
+ ),
+ body: AdwViewStack(
+ index: value,
+ children: const [
+ Center(
+ child: Text('World'),
+ ),
+ Center(
+ child: Text('Alarm'),
+ ),
+ Center(
+ child: Text('Stopwatch'),
+ ),
+ Center(
+ child: Text('Timer'),
),
],
- );
- },
+ ),
+ ),
);
}
}
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 07475ad..45ceb67 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -7,7 +7,7 @@ packages:
name: adwaita
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.0"
+ version: "0.5.1"
args:
dependency: transitive
description:
@@ -22,13 +22,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
- bitsdojo_window:
- dependency: "direct main"
- description:
- name: bitsdojo_window
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.1.1+1"
bitsdojo_window_linux:
dependency: transitive
description:
@@ -98,7 +91,7 @@ packages:
name: dbus
url: "https://pub.dartlang.org"
source: hosted
- version: "0.6.6"
+ version: "0.7.1"
desktop_multi_window:
dependency: "direct main"
description:
@@ -155,7 +148,7 @@ packages:
name: gsettings
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.3"
+ version: "0.2.5"
http:
dependency: transitive
description:
@@ -184,6 +177,13 @@ packages:
relative: true
source: path
version: "1.0.0"
+ libadwaita_bitsdojo:
+ dependency: "direct main"
+ description:
+ name: libadwaita_bitsdojo
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.5.0"
matcher:
dependency: transitive
description:
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 3591c68..c69b1c8 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -2,19 +2,19 @@ name: example
description: A new Flutter project.
publish_to: none
-version: 1.0.0+1
+version: 1.0.0+2
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
- adwaita: "0.1.0"
- bitsdojo_window: ">=0.1.1+1 <1.0.0"
+ adwaita: "0.5.1"
desktop_multi_window: ">=0.0.1 <1.0.0"
flutter:
sdk: flutter
libadwaita:
path: ../
+ libadwaita_bitsdojo: ">=0.5.0 <1.0.0"
dev_dependencies:
flutter_test:
diff --git a/lib/src/models/models.dart b/lib/src/models/models.dart
index e0ffc24..5a9cbb4 100644
--- a/lib/src/models/models.dart
+++ b/lib/src/models/models.dart
@@ -1,2 +1,2 @@
export 'view_switcher_data.dart';
-export 'view_switcher_style.dart';
+export 'view_switcher_policy.dart';
diff --git a/lib/src/models/view_switcher_policy.dart b/lib/src/models/view_switcher_policy.dart
new file mode 100644
index 0000000..858cd48
--- /dev/null
+++ b/lib/src/models/view_switcher_policy.dart
@@ -0,0 +1 @@
+enum ViewSwitcherPolicy { wide, narrow }
diff --git a/lib/src/models/view_switcher_style.dart b/lib/src/models/view_switcher_style.dart
deleted file mode 100644
index 0fa9143..0000000
--- a/lib/src/models/view_switcher_style.dart
+++ /dev/null
@@ -1 +0,0 @@
-enum ViewSwitcherStyle { desktop, mobile }
diff --git a/lib/src/utils/colors.dart b/lib/src/utils/colors.dart
index b733c3b..3cee49b 100644
--- a/lib/src/utils/colors.dart
+++ b/lib/src/utils/colors.dart
@@ -23,13 +23,18 @@ extension ColorBrightness on Color {
}
}
-Color borderLight = Colors.black.withOpacity(0.18);
-Color borderDark = const Color(0xFF454545);
+class AdwDefaultColors {
+ static Color borderLight = Colors.black.withOpacity(0.18);
+ static Color borderDark = const Color(0xFF454545);
+
+ static Color blue = const Color(0xFF3584e4);
+}
extension BorderContext on BuildContext {
bool get _isDark => Theme.of(this).brightness == Brightness.dark;
- Color get borderColor => _isDark ? borderDark : borderLight;
+ Color get borderColor =>
+ _isDark ? AdwDefaultColors.borderDark : AdwDefaultColors.borderLight;
Color get checkboxColor =>
_isDark ? const Color(0xFF535353) : const Color(0xFFE0E0E0);
diff --git a/lib/src/widgets/adw/about_window.dart b/lib/src/widgets/adw/about_window.dart
index fd22c54..d5a0db2 100644
--- a/lib/src/widgets/adw/about_window.dart
+++ b/lib/src/widgets/adw/about_window.dart
@@ -102,6 +102,7 @@ class _AdwAboutWindowState extends State {
widget.headerbar?.call([leading], text) ??
AdwHeaderBar(
start: [leading],
+ autoPositionWindowButtons: false,
onClose: Navigator.of(context).pop,
isTransparent: true,
title: text,
@@ -182,6 +183,15 @@ class _AdwAboutWindowState extends State {
]
: currentPage == 1
? widget.credits!
+ .map(
+ (e) => Padding(
+ padding: const EdgeInsets.only(
+ bottom: 10,
+ ),
+ child: e,
+ ),
+ )
+ .toList()
: [
if (widget.copyright != null)
Text(widget.copyright!),
diff --git a/lib/src/widgets/adw/action_row.dart b/lib/src/widgets/adw/action_row.dart
index bb05688..906bd85 100644
--- a/lib/src/widgets/adw/action_row.dart
+++ b/lib/src/widgets/adw/action_row.dart
@@ -1,7 +1,5 @@
import 'package:flutter/material.dart';
-class AdwActionRowStyle {}
-
class AdwActionRow extends StatelessWidget {
const AdwActionRow({
Key? key,
@@ -12,19 +10,33 @@ class AdwActionRow extends StatelessWidget {
this.subtitle,
this.autofocus = false,
this.enabled = true,
- this.style,
this.contentPadding,
}) : super(key: key);
+ /// The starting elemets of this row
final Widget? start;
+
+ /// The ending elements of this row
final Widget? end;
+
+ /// The title of this row
final String title;
+
+ /// The subtitle of this row
final String? subtitle;
+
+ /// Executed when this Action row is pressed
final VoidCallback? onActivated;
+
+ /// Whether to focus automatically when this widget is visible
+ /// defaults to false
final bool autofocus;
+
+ /// Whether this action row is enabled or not, defaults to true
final bool enabled;
+
+ /// The padding b/w content of this Action row
final EdgeInsets? contentPadding;
- final AdwActionRowStyle? style;
@override
Widget build(BuildContext context) {
diff --git a/lib/src/widgets/adw/clamp.dart b/lib/src/widgets/adw/clamp.dart
index 830b687..ff9c2ae 100644
--- a/lib/src/widgets/adw/clamp.dart
+++ b/lib/src/widgets/adw/clamp.dart
@@ -23,12 +23,25 @@ class AdwClamp extends StatefulWidget {
}) : isScrollable = true,
super(key: key);
+ /// Whether this clamp is scrollable or not
final bool isScrollable;
+
+ /// The controller for the scrollable clamp
final ScrollController? controller;
+
+ /// Whether to center the elements horizontally of the clamp
final bool center;
+
+ /// The child of this clamp
final Widget child;
+
+ /// Sets the maximum size allocated to the child.
final double maximumSize;
+
+ /// The padding around this clamp
final EdgeInsets padding;
+
+ /// The margin around this clamp
final EdgeInsets margin;
@override
diff --git a/lib/src/widgets/adw/combo_row.dart b/lib/src/widgets/adw/combo_row.dart
index d8448cc..b72c51b 100644
--- a/lib/src/widgets/adw/combo_row.dart
+++ b/lib/src/widgets/adw/combo_row.dart
@@ -3,13 +3,14 @@ import 'package:libadwaita/src/utils/colors.dart';
import 'package:libadwaita/src/widgets/adw/button.dart';
import 'package:popover_gtk/popover_gtk.dart';
-/// This is the stateful widget that the main application instantiates.
class AdwComboRow extends StatefulWidget {
const AdwComboRow({
Key? key,
this.choices = const [],
this.start,
this.end,
+ required this.selectedIndex,
+ required this.onSelected,
required this.title,
this.subtitle,
this.autofocus = false,
@@ -17,47 +18,49 @@ class AdwComboRow extends StatefulWidget {
this.contentPadding,
}) : super(key: key);
+ /// The choices available for this combo row
final List choices;
+
+ /// The index of the selected choice
+ final int selectedIndex;
+
+ /// Executed when a choice is selected
+ final ValueSetter onSelected;
+
+ /// The starting elemets of this row
final Widget? start;
+
+ /// The ending elements of this row
final Widget? end;
+
+ /// The title of this row
final String title;
+
+ /// The subtitle of this row
final String? subtitle;
+
+ /// Whether to focus automatically when this widget is visible
+ /// defaults to false
final bool autofocus;
+
+ /// Whether this combo row is enabled or not, defaults to true
final bool enabled;
+
+ /// The padding b/w content of this Combo row
final EdgeInsets? contentPadding;
@override
State createState() => _AdwComboRowState();
}
-/// This is the private State class that goes with MyStatefulWidget.
class _AdwComboRowState extends State {
_AdwComboRowState();
- bool taped = false;
- int selected = 0;
final GlobalKey<_AdwComboButtonState> _comboButtonState =
GlobalKey<_AdwComboButtonState>();
late AdwComboButton button;
- @override
- void initState() {
- button = AdwComboButton(
- key: _comboButtonState,
- choices: widget.choices,
- getSelected: () {
- return selected;
- },
- setSelected: (select) {
- setState(() {
- selected = select;
- });
- },
- );
- super.initState();
- }
-
@override
Widget build(BuildContext context) {
return InkWell(
@@ -92,12 +95,19 @@ class _AdwComboRowState extends State {
const SizedBox(width: 10),
Flexible(
child: Text(
- widget.choices[selected],
+ widget.choices[widget.selectedIndex],
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 5),
- button,
+ AdwComboButton(
+ key: _comboButtonState,
+ choices: widget.choices,
+ selectedIndex: widget.selectedIndex,
+ onSelected: (val) {
+ widget.onSelected(val);
+ },
+ ),
const SizedBox(width: 10),
],
),
@@ -112,13 +122,18 @@ class AdwComboButton extends StatefulWidget {
const AdwComboButton({
Key? key,
this.choices = const [],
- required this.setSelected,
- required this.getSelected,
+ required this.onSelected,
+ required this.selectedIndex,
}) : super(key: key);
+ /// The choices available for this combo row
final List choices;
- final ValueSetter setSelected;
- final ValueGetter getSelected;
+
+ /// Executed when a choice is selected
+ final ValueSetter onSelected;
+
+ /// The index of the selected choice
+ final int selectedIndex;
@override
State createState() => _AdwComboButtonState();
@@ -131,13 +146,12 @@ class _AdwComboButtonState extends State {
bool active = false;
@override
- Widget build(BuildContext context) {
- return const Icon(Icons.arrow_drop_down);
- }
+ Widget build(BuildContext context) => const Icon(Icons.arrow_drop_down);
void show() {
showPopover(
context: context,
+ arrowHeight: 14,
barrierColor: Colors.transparent,
shadow: [
BoxShadow(
@@ -145,35 +159,35 @@ class _AdwComboButtonState extends State {
blurRadius: 6,
),
],
- bodyBuilder: (_) => Column(
- mainAxisSize: MainAxisSize.min,
- children: List.generate(widget.choices.length, (int index) {
- return AdwButton.flat(
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Flexible(
- child: Text(
- widget.choices[index],
- overflow: TextOverflow.ellipsis,
+ bodyBuilder: (_) => SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: List.generate(
+ widget.choices.length,
+ (int index) => AdwButton.flat(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Flexible(
+ child: Text(
+ widget.choices[index],
+ overflow: TextOverflow.ellipsis,
+ ),
),
- ),
- if (index == widget.getSelected())
- const Icon(Icons.check, size: 20),
- ],
+ if (index == widget.selectedIndex)
+ const Icon(Icons.check, size: 20),
+ ],
+ ),
+ onPressed: () {
+ widget.onSelected(index);
+ setState(() {});
+ Navigator.of(context).pop();
+ },
),
- onPressed: () {
- setState(() {
- widget.setSelected(index);
- //if you want to assign the index somewhere to check
- });
- Navigator.of(context).pop();
- },
- );
- }),
+ ),
+ ),
),
width: 200,
- height: null,
backgroundColor: Theme.of(context).cardColor,
).whenComplete(() => setState(() => active = false));
}
diff --git a/lib/src/widgets/adw/flap.dart b/lib/src/widgets/adw/flap.dart
index cad2539..f8b9011 100644
--- a/lib/src/widgets/adw/flap.dart
+++ b/lib/src/widgets/adw/flap.dart
@@ -7,28 +7,24 @@ import 'package:libadwaita/src/utils/colors.dart';
enum FoldPolicy { never, always, auto }
enum FlapPosition { start, end }
-class AdwFlap extends StatefulWidget {
- const AdwFlap({
- Key? key,
- required this.flap,
- required this.child,
- this.locked = false,
- this.flapController,
+class FlapStyle {
+ FlapStyle({
this.seperator,
- this.foldPolicy = FoldPolicy.auto,
- this.flapPosition = FlapPosition.start,
+ this.locked = false,
this.breakpoint = 900,
this.flapWidth = 270.0,
- }) : super(key: key);
+ this.foldPolicy = FoldPolicy.auto,
+ this.flapPosition = FlapPosition.start,
+ });
- final Widget flap;
- final Widget child;
+ /// The seperator b/w flap and the content
final Widget? seperator;
+ /// The FoldPolicy of this flap, defaults to auto
final FoldPolicy foldPolicy;
- final FlapPosition flapPosition;
- final FlapController? flapController;
+ /// The FlapPosition of this flap, defaults to start
+ final FlapPosition flapPosition;
/// The breakpoint for small devices
final double breakpoint;
@@ -41,6 +37,29 @@ class AdwFlap extends StatefulWidget {
/// state when screen is resized or
/// not
final bool locked;
+}
+
+class AdwFlap extends StatefulWidget {
+ AdwFlap({
+ Key? key,
+ required this.flap,
+ required this.child,
+ this.controller,
+ FlapStyle? style,
+ }) : style = style ?? FlapStyle(),
+ super(key: key);
+
+ /// The flap widget itself, Mainly is a `AdwSidebar` instance
+ final Widget flap;
+
+ /// The content of the page
+ final Widget child;
+
+ /// The style of this flap
+ final FlapStyle style;
+
+ /// The controller for this flap
+ final FlapController? controller;
@override
_AdwFlapState createState() => _AdwFlapState();
@@ -57,10 +76,10 @@ class _AdwFlapState extends State {
void initState() {
super.initState();
- if (widget.flapController == null) {
+ if (widget.controller == null) {
_controller = FlapController();
} else {
- _controller = widget.flapController!;
+ _controller = widget.controller!;
}
_controller.addListener(rebuild);
@@ -70,9 +89,9 @@ class _AdwFlapState extends State {
void updateFlapData() {
_controller
- ..policy = widget.foldPolicy
- ..position = widget.flapPosition
- ..locked = widget.locked;
+ ..policy = widget.style.foldPolicy
+ ..position = widget.style.flapPosition
+ ..locked = widget.style.locked;
}
@override
@@ -98,7 +117,7 @@ class _AdwFlapState extends State {
final flap = SlideHide(
isHidden: _controller.shouldHide(),
- width: widget.flapWidth,
+ width: widget.style.flapWidth,
child: SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
@@ -106,13 +125,13 @@ class _AdwFlapState extends State {
),
);
- final seperator = widget.seperator ??
+ final seperator = widget.style.seperator ??
Container(
width: 1,
color: context.borderColor,
);
- final widgets = widget.flapPosition == FlapPosition.start
+ final widgets = widget.style.flapPosition == FlapPosition.start
? [flap, seperator, content]
: [content, seperator, flap];
@@ -125,10 +144,10 @@ class _AdwFlapState extends State {
// affected by window resizes.
// If FoldPolicy is auto, then close / open the sidebar depending on the
// state
- final isMobile = size.width < widget.breakpoint;
+ final isMobile = size.width < widget.style.breakpoint;
_controller.updateModalState(context, state: isMobile);
- switch (widget.foldPolicy) {
+ switch (widget.style.foldPolicy) {
case FoldPolicy.never:
case FoldPolicy.always:
break;
diff --git a/lib/src/widgets/adw/header_bar.dart b/lib/src/widgets/adw/header_bar.dart
index 9ac7245..7b8f2ae 100644
--- a/lib/src/widgets/adw/header_bar.dart
+++ b/lib/src/widgets/adw/header_bar.dart
@@ -8,6 +8,12 @@ import 'package:gsettings/gsettings.dart';
import 'package:libadwaita/src/utils/colors.dart';
import 'package:libadwaita/src/widgets/widgets.dart';
+/// To be used with nativeshell package as it doesn't have this method
+Future _maximizeOrRestore(dynamic window) async {
+ final dynamic flags = await window.getWindowStateFlags();
+ await window.setMaximized(!(flags.maximized as bool));
+}
+
class AdwHeaderBar extends StatefulWidget {
/// If you use with window_decorations
/// If you don't want that. use AdwHeaderBar.custom
@@ -23,9 +29,10 @@ class AdwHeaderBar extends StatefulWidget {
this.onDoubleTap,
this.onHeaderDrag,
this.start = const [],
- this.title = const SizedBox(),
+ this.title,
this.end = const [],
this.textStyle,
+ this.autoPositionWindowButtons = true,
this.isTransparent = false,
this.padding = const EdgeInsets.only(left: 3, right: 5),
this.titlebarSpace = 6,
@@ -37,19 +44,19 @@ class AdwHeaderBar extends StatefulWidget {
onPressed: onClose,
themeType: themeType,
windowDecor: windowDecor,
- buttonType: AdwWindowButtonType.close,
+ buttonType: WindowButtonType.close,
),
maximizeBtn = AdwWindowButton(
onPressed: onMaximize,
themeType: themeType,
windowDecor: windowDecor,
- buttonType: AdwWindowButtonType.maximize,
+ buttonType: WindowButtonType.maximize,
),
minimizeBtn = AdwWindowButton(
themeType: themeType,
onPressed: onMinimize,
windowDecor: windowDecor,
- buttonType: AdwWindowButtonType.minimize,
+ buttonType: WindowButtonType.minimize,
),
super(key: key);
@@ -61,6 +68,7 @@ class AdwHeaderBar extends StatefulWidget {
this.title = const SizedBox(),
this.end = const [],
this.textStyle,
+ this.autoPositionWindowButtons = true,
this.isTransparent = false,
this.padding = const EdgeInsets.only(left: 3, right: 5),
this.titlebarSpace = 6,
@@ -73,7 +81,7 @@ class AdwHeaderBar extends StatefulWidget {
AdwHeaderBar.bitsdojo({
Key? key,
- /// The appWindow object from bitsdojo_window package
+ /// The appWindow object from libadwaita_bitsdojo package
required dynamic appWindow,
Widget Function(
String name,
@@ -86,6 +94,7 @@ class AdwHeaderBar extends StatefulWidget {
this.title = const SizedBox(),
this.end = const [],
this.textStyle,
+ this.autoPositionWindowButtons = true,
this.isTransparent = false,
this.padding = const EdgeInsets.only(left: 3, right: 5),
this.titlebarSpace = 6,
@@ -98,7 +107,7 @@ class AdwHeaderBar extends StatefulWidget {
onPressed: appWindow?.close as void Function()?,
themeType: themeType,
windowDecor: windowDecor,
- buttonType: AdwWindowButtonType.close,
+ buttonType: WindowButtonType.close,
)
: null,
maximizeBtn = showMaximize
@@ -106,7 +115,7 @@ class AdwHeaderBar extends StatefulWidget {
onPressed: appWindow?.maximize as void Function()?,
themeType: themeType,
windowDecor: windowDecor,
- buttonType: AdwWindowButtonType.maximize,
+ buttonType: WindowButtonType.maximize,
)
: null,
minimizeBtn = showMinimize
@@ -114,7 +123,7 @@ class AdwHeaderBar extends StatefulWidget {
onPressed: appWindow?.minimize as void Function()?,
themeType: themeType,
windowDecor: windowDecor,
- buttonType: AdwWindowButtonType.minimize,
+ buttonType: WindowButtonType.minimize,
)
: null,
onHeaderDrag = appWindow?.startDragging as void Function()?,
@@ -124,12 +133,13 @@ class AdwHeaderBar extends StatefulWidget {
AdwHeaderBar.customBitsdojo({
Key? key,
- /// The appWindow object from bitsdojo_window package
+ /// The appWindow object from libadwaita_bitsdojo package
required dynamic appWindow,
this.start = const [],
this.title = const SizedBox(),
this.end = const [],
this.textStyle,
+ this.autoPositionWindowButtons = true,
this.isTransparent = false,
this.padding = const EdgeInsets.only(left: 3, right: 5),
this.titlebarSpace = 6,
@@ -161,20 +171,33 @@ class AdwHeaderBar extends StatefulWidget {
this.title = const SizedBox(),
this.end = const [],
this.textStyle,
+ this.autoPositionWindowButtons = true,
this.isTransparent = false,
this.padding = const EdgeInsets.only(left: 3, right: 5),
this.titlebarSpace = 6,
this.height = 51,
+ bool showMinimize = true,
+ bool showMaximize = true,
bool showClose = true,
}) : onHeaderDrag = window?.performDrag as void Function()?,
onDoubleTap = null,
- minimizeBtn = null,
- maximizeBtn = null,
+ minimizeBtn = AdwWindowButton(
+ onPressed: showMinimize ? () => window.setMinimized(true) : null,
+ themeType: themeType,
+ windowDecor: windowDecor,
+ buttonType: WindowButtonType.minimize,
+ ),
+ maximizeBtn = AdwWindowButton(
+ onPressed: showMaximize ? () => _maximizeOrRestore(window) : null,
+ themeType: themeType,
+ windowDecor: windowDecor,
+ buttonType: WindowButtonType.maximize,
+ ),
closeBtn = AdwWindowButton(
onPressed: showClose ? window.close as void Function()? : null,
themeType: themeType,
windowDecor: windowDecor,
- buttonType: AdwWindowButtonType.close,
+ buttonType: WindowButtonType.close,
),
super(key: key);
@@ -187,15 +210,18 @@ class AdwHeaderBar extends StatefulWidget {
this.title = const SizedBox(),
this.end = const [],
this.textStyle,
+ this.autoPositionWindowButtons = true,
this.isTransparent = false,
this.padding = const EdgeInsets.only(left: 3, right: 5),
this.titlebarSpace = 6,
this.height = 51,
+ Widget Function(VoidCallback onTap)? minimizeBtn,
+ Widget Function(VoidCallback onTap)? maximizeBtn,
Widget Function(VoidCallback onTap)? closeBtn,
}) : onHeaderDrag = window?.performDrag as void Function()?,
- onDoubleTap = null,
- minimizeBtn = null,
- maximizeBtn = null,
+ onDoubleTap = (() => _maximizeOrRestore(window)),
+ minimizeBtn = minimizeBtn?.call(() => window.setMinimized(true)),
+ maximizeBtn = maximizeBtn?.call(() => _maximizeOrRestore(window)),
closeBtn = closeBtn?.call(window.close as void Function()),
super(key: key);
@@ -203,7 +229,7 @@ class AdwHeaderBar extends StatefulWidget {
final List start;
/// The center widget for the headerbar
- final Widget title;
+ final Widget? title;
/// The trailing widget for the headerbar
final List end;
@@ -224,6 +250,12 @@ class AdwHeaderBar extends StatefulWidget {
/// The height of the headerbar
final double height;
+ /// Whether to automatically place the window buttons according to
+ /// the Platform, defaults to true
+ /// If false then it will follow the general Windows like window buttons
+ /// placement
+ final bool autoPositionWindowButtons;
+
/// The padding inside the headerbar
final EdgeInsets padding;
@@ -246,33 +278,39 @@ class _AdwHeaderBarState extends State {
widget.minimizeBtn != null ||
widget.maximizeBtn != null;
- late ValueNotifier> seperator =
- ValueNotifier(['', 'minimize,maximize,close']);
+ late ValueNotifier> seperator = ValueNotifier([
+ '',
+ 'minimize,maximize,close',
+ ]);
@override
void initState() {
super.initState();
- late final order = ValueNotifier(':minimize,maximize,close');
- void updateSep() {
- if (mounted) {
- seperator.value = order.value.split(':');
+ if (widget.autoPositionWindowButtons) {
+ void updateSep(String order) {
+ if (!mounted) return;
+ seperator.value = order.split(':');
}
- }
- if (Platform.isLinux) {
- final buttonLayout = ValueNotifier(null);
- final schema = GSettings('org.gnome.desktop.wm.preferences');
- WidgetsBinding.instance?.addPostFrameCallback((_) async {
- buttonLayout.value = await schema.get('button-layout') as DBusString;
- if (buttonLayout.value != null) {
- order.value = buttonLayout.value!.value;
- }
- updateSep();
- });
- } else if (Platform.isMacOS) {
- order.value = 'close,maximize,minimize:';
- updateSep();
+ if (Platform.isWindows) {
+ updateSep(':minimize,maximize,close');
+ } else if (Platform.isMacOS) {
+ updateSep('close,maximize,minimize:');
+ } else if (Platform.isLinux) {
+ updateSep(':close');
+
+ final schema = GSettings('org.gnome.desktop.wm.preferences');
+
+ WidgetsBinding.instance?.addPostFrameCallback((_) async {
+ final buttonLayout = await schema.get('button-layout') as DBusString?;
+ if (buttonLayout != null) {
+ updateSep(buttonLayout.value);
+ }
+ });
+ } else {
+ updateSep(':');
+ }
}
}
@@ -315,8 +353,8 @@ class _AdwHeaderBarState extends State {
valueListenable: seperator,
builder: (context, sep, _) => DefaultTextStyle.merge(
style: const TextStyle(
- fontWeight: FontWeight.bold,
fontSize: 14,
+ fontWeight: FontWeight.bold,
).merge(widget.textStyle),
child: NavigationToolbar(
leading: Row(
@@ -326,26 +364,14 @@ class _AdwHeaderBarState extends State {
SizedBox(width: widget.titlebarSpace),
for (var i in sep[0].split(','))
if (windowButtons[i] != null) windowButtons[i]!,
- ...widget.start.map(
- (e) => Padding(
- padding:
- const EdgeInsets.symmetric(horizontal: 3),
- child: e,
- ),
- ),
+ ...widget.start
],
),
middle: widget.title,
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
- ...widget.end.map(
- (e) => Padding(
- padding:
- const EdgeInsets.symmetric(horizontal: 3),
- child: e,
- ),
- ),
+ ...widget.end,
if (hasWindowControls && sep[1].split(',').isNotEmpty)
SizedBox(width: widget.titlebarSpace),
for (var i in sep[1].split(','))
diff --git a/lib/src/widgets/adw/new/scaffold.dart b/lib/src/widgets/adw/new/scaffold.dart
index f553749..555cdca 100644
--- a/lib/src/widgets/adw/new/scaffold.dart
+++ b/lib/src/widgets/adw/new/scaffold.dart
@@ -3,24 +3,27 @@ import 'package:libadwaita/src/controllers/flap_controller.dart';
import 'package:libadwaita/src/widgets/widgets.dart';
class AdwScaffold extends StatefulWidget {
- AdwScaffold({
+ const AdwScaffold({
Key? key,
required this.body,
+ this.flap,
+ this.flapStyle,
this.flapController,
- Widget? drawer,
- this.bottomNavigationBar,
- }) :
-
- /// Use less width to match libadwaita
- drawer = drawer != null ? SizedBox(width: 200, child: drawer) : null,
- super(key: key);
+ this.headerbar,
+ this.viewSwitcher,
+ }) : super(key: key);
final Widget body;
+
+ final AdwSidebar Function(bool isDrawer)? flap;
+
final FlapController? flapController;
- final Widget? drawer;
- /// Remove this when ViewSwitcher becomes adaptive
- final Widget? bottomNavigationBar;
+ final FlapStyle? flapStyle;
+
+ final Widget? Function(Widget? viewSwitcher)? headerbar;
+
+ final Widget? viewSwitcher;
@override
_AdwScaffoldState createState() => _AdwScaffoldState();
@@ -32,24 +35,59 @@ class _AdwScaffoldState extends State {
@override
void initState() {
super.initState();
- if (widget.body is AdwFlap) {
- _flapController = widget.flapController ?? FlapController();
- }
+ _flapController = widget.flapController ?? FlapController();
}
@override
Widget build(BuildContext context) {
- return Scaffold(
- drawerEnableOpenDragGesture:
- _flapController?.shouldEnableDrawerGesture(FlapPosition.start) ??
- false,
- endDrawerEnableOpenDragGesture:
- _flapController?.shouldEnableDrawerGesture(FlapPosition.end) ?? false,
- onDrawerChanged: _flapController?.onDrawerChanged,
- drawer: widget.drawer,
- endDrawer: widget.drawer,
- body: widget.body,
- bottomNavigationBar: widget.bottomNavigationBar,
+ final isMobile = MediaQuery.of(context).size.width <= 600;
+ final headerbar =
+ widget.headerbar?.call(!isMobile ? widget.viewSwitcher : null);
+ final flap = widget.flap != null
+ ? SizedBox(
+ width: 200,
+ child: Drawer(elevation: 25, child: widget.flap!(true)),
+ )
+ : null;
+
+ return SafeArea(
+ child: Column(
+ children: [
+ if (headerbar != null) headerbar,
+ Expanded(
+ child: Scaffold(
+ drawerEnableOpenDragGesture: _flapController
+ ?.shouldEnableDrawerGesture(FlapPosition.start) ??
+ false,
+ endDrawerEnableOpenDragGesture: _flapController
+ ?.shouldEnableDrawerGesture(FlapPosition.end) ??
+ false,
+ onDrawerChanged: _flapController?.onDrawerChanged,
+ drawer: flap,
+ endDrawer: flap,
+ body: widget.flap != null
+ ? AdwFlap(
+ flap: widget.flap!(false),
+ controller: widget.flapController,
+ style: widget.flapStyle,
+ child: widget.body,
+ )
+ : widget.body,
+ bottomNavigationBar: widget.viewSwitcher != null && isMobile
+ ? SizedBox(
+ height: 51,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ widget.viewSwitcher!,
+ ],
+ ),
+ )
+ : null,
+ ),
+ )
+ ],
+ ),
);
}
}
diff --git a/lib/src/widgets/adw/new/sidebar.dart b/lib/src/widgets/adw/new/sidebar.dart
index 83749ad..6cda8d8 100644
--- a/lib/src/widgets/adw/new/sidebar.dart
+++ b/lib/src/widgets/adw/new/sidebar.dart
@@ -16,7 +16,7 @@ class AdwSidebar extends StatelessWidget {
required this.onSelected,
this.width = 270.0,
this.color,
- this.border,
+ this.isDrawer = false,
this.controller,
this.padding = const EdgeInsets.symmetric(vertical: 6, horizontal: 6),
required List children,
@@ -24,6 +24,7 @@ class AdwSidebar extends StatelessWidget {
children.length,
(index) => _AdwSidebarItemBuilder(
item: (context) => children[index],
+ isDrawer: isDrawer,
isSelected: index == currentIndex,
onSelected: () => onSelected(index),
),
@@ -36,7 +37,7 @@ class AdwSidebar extends StatelessWidget {
required this.onSelected,
this.width = 270.0,
this.color,
- this.border,
+ this.isDrawer = false,
this.controller,
this.padding = const EdgeInsets.symmetric(vertical: 6, horizontal: 6),
required AdwSidebarItem Function(
@@ -53,6 +54,7 @@ class AdwSidebar extends StatelessWidget {
item: (context) =>
itemBuilder(context, index, currentIndex == index),
isSelected: currentIndex == index,
+ isDrawer: isDrawer,
onSelected: () => onSelected(index),
),
),
@@ -72,6 +74,9 @@ class AdwSidebar extends StatelessWidget {
/// Called when one of the Sidebar item is selected.
final Function(int index) onSelected;
+ /// Is the Sidebar present in the Drawer of the Scaffold
+ final bool isDrawer;
+
/// The width of the sidebar.
///
/// Defaults to `270.0`.
@@ -80,9 +85,6 @@ class AdwSidebar extends StatelessWidget {
/// The background color of the sidebar.
final Color? color;
- /// The border around the sidebar.
- final Border? border;
-
/// Delegate in charge of supplying children to the internal list
/// of this widget.
final List _childrenDelegate;
@@ -153,12 +155,14 @@ class _AdwSidebarItemBuilder extends StatelessWidget {
Key? key,
required this.item,
required this.isSelected,
+ required this.isDrawer,
this.onSelected,
}) : super(key: key);
final AdwSidebarItem Function(BuildContext context) item;
final bool isSelected;
final VoidCallback? onSelected;
+ final bool isDrawer;
@override
Widget build(BuildContext context) {
@@ -169,7 +173,12 @@ class _AdwSidebarItemBuilder extends StatelessWidget {
margin: const EdgeInsets.only(bottom: 2),
textStyle: const TextStyle(fontWeight: FontWeight.normal),
padding: currentItem.padding,
- onPressed: onSelected,
+ onPressed: () {
+ onSelected?.call();
+ if (isDrawer) {
+ Navigator.of(context).pop();
+ }
+ },
isActive: isSelected,
child: Row(
children: [
diff --git a/lib/src/widgets/adw/new/text_field.dart b/lib/src/widgets/adw/new/text_field.dart
index b141d5d..b094525 100644
--- a/lib/src/widgets/adw/new/text_field.dart
+++ b/lib/src/widgets/adw/new/text_field.dart
@@ -7,13 +7,34 @@ class AdwTextField extends StatelessWidget {
this.keyboardType,
this.onChanged,
this.icon,
+ this.prefixIcon,
+ this.onSubmitted,
this.initialValue,
+ this.autofocus = false,
}) : super(key: key);
+ /// Will automatically focus on this field when it's visible
+ final bool autofocus;
+
+ /// To be run when you submit this field using Enter key
+ final ValueChanged? onSubmitted;
+
+ /// The controller for the field
final TextEditingController? controller;
+
+ /// Keyboard Type for this field
final TextInputType? keyboardType;
+
+ /// Runs when value is changed from this field
final Function(String)? onChanged;
+
+ /// The suffix icon for this field
final IconData? icon;
+
+ /// The prefix icon for this field
+ final IconData? prefixIcon;
+
+ /// The initial value (if any) for this field
final String? initialValue;
@override
@@ -21,25 +42,16 @@ class AdwTextField extends StatelessWidget {
return TextFormField(
initialValue: initialValue,
controller: controller,
+ autofocus: autofocus,
+ onFieldSubmitted: onSubmitted,
keyboardType: keyboardType,
decoration: InputDecoration(
- enabledBorder: const OutlineInputBorder(
- borderRadius: BorderRadius.all(
- Radius.circular(8),
- ),
- borderSide: BorderSide(
- color: Colors.transparent,
- ),
- ),
- focusedBorder: OutlineInputBorder(
- borderRadius: const BorderRadius.all(
- Radius.circular(8),
- ),
- borderSide: BorderSide(
- color: Theme.of(context).colorScheme.secondary,
- ),
- ),
- isDense: true,
+ prefixIcon: prefixIcon != null
+ ? Icon(
+ prefixIcon,
+ color: Theme.of(context).textTheme.headline1?.color,
+ )
+ : null,
suffixIcon: icon != null
? Icon(
icon,
diff --git a/lib/src/widgets/adw/new/window_button.dart b/lib/src/widgets/adw/new/window_button.dart
index cc8be66..6599c40 100644
--- a/lib/src/widgets/adw/new/window_button.dart
+++ b/lib/src/widgets/adw/new/window_button.dart
@@ -3,7 +3,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:libadwaita/src/utils/colors.dart';
import 'package:libadwaita/src/widgets/widgets.dart';
-enum AdwWindowButtonType { close, maximize, minimize }
+enum WindowButtonType { close, maximize, minimize }
class AdwWindowButton extends StatelessWidget {
const AdwWindowButton({
@@ -14,15 +14,21 @@ class AdwWindowButton extends StatelessWidget {
this.windowDecor,
}) : super(key: key);
+ /// The ThemeType from the window_decorations package, nullable
final dynamic themeType;
+ /// The windowDecor object from window_decorations package
final Widget Function(
String name,
dynamic type,
void Function()? windowDecor,
)? windowDecor;
+
+ /// Executed when this button is pressed
final VoidCallback? onPressed;
- final AdwWindowButtonType buttonType;
+
+ /// The WindowButtonType for this window
+ final WindowButtonType buttonType;
@override
Widget build(BuildContext context) {
diff --git a/lib/src/widgets/adw/preferences_group.dart b/lib/src/widgets/adw/preferences_group.dart
index 3b86e21..b7733e4 100644
--- a/lib/src/widgets/adw/preferences_group.dart
+++ b/lib/src/widgets/adw/preferences_group.dart
@@ -49,7 +49,7 @@ class AdwPreferencesGroup extends StatelessWidget {
if (title != null) ...[
Text(
title!,
- style: titleStyle ?? Theme.of(context).textTheme.headline6,
+ style: titleStyle ?? Theme.of(context).textTheme.headline5,
),
if (description != null)
Text(
@@ -57,7 +57,7 @@ class AdwPreferencesGroup extends StatelessWidget {
style: descriptionStyle ??
Theme.of(context).textTheme.bodyText2,
),
- const SizedBox(height: 8),
+ const SizedBox(height: 12),
],
],
),
diff --git a/lib/src/widgets/adw/switch.dart b/lib/src/widgets/adw/switch.dart
index 9f6447c..3e08890 100644
--- a/lib/src/widgets/adw/switch.dart
+++ b/lib/src/widgets/adw/switch.dart
@@ -9,7 +9,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:libadwaita/src/utils/colors.dart';
-import 'package:libadwaita/src/widgets/widgets.dart';
// Examples can assume:
// bool _lights = false;
@@ -313,8 +312,8 @@ class _AdwSwitchState extends State with TickerProviderStateMixin {
activeColor: widget.activeColor ??
(switchTheme.thumbColor != null
? switchTheme.thumbColor!.resolve({MaterialState.selected}) ??
- AdwColors.blue.backgroundColor
- : AdwColors.blue.backgroundColor),
+ AdwDefaultColors.blue
+ : AdwDefaultColors.blue),
trackColor: widget.trackColor ??
(switchTheme.trackColor != null
? switchTheme.trackColor!.resolve({MaterialState.focused}) ??
diff --git a/lib/src/widgets/adw/view_switcher.dart b/lib/src/widgets/adw/view_switcher.dart
index 4f6eb9b..330a0df 100644
--- a/lib/src/widgets/adw/view_switcher.dart
+++ b/lib/src/widgets/adw/view_switcher.dart
@@ -9,7 +9,7 @@ class AdwViewSwitcher extends StatelessWidget {
required this.onViewChanged,
required this.currentIndex,
this.badgeColor,
- this.style,
+ this.policy,
@Deprecated('This parameter is no longer in use')
double height = 55,
@Deprecated(
@@ -17,23 +17,37 @@ class AdwViewSwitcher extends StatelessWidget {
'This feature was deprecated after v1.0.0-rc.2',
)
bool? expanded,
+ this.paddingIcon,
}) : assert(tabs.length >= 2, 'Minimum 2 tabs are required'),
super(key: key);
+ /// The color of the badge at the top right of the tab's icon
final Color? badgeColor;
+
+ /// The tabs of this view switcher
final List tabs;
+
+ /// Executed when the view switcher tab is changed
final ValueChanged onViewChanged;
- final ViewSwitcherStyle? style;
+
+ /// The Policy of this view switcher defaults to wide for desktop and
+ /// narrow for mobile
+ final ViewSwitcherPolicy? policy;
+
+ /// The current index of the selected view
final int currentIndex;
+ /// The Padding for the icon of the view switcher tab
+ final EdgeInsets? paddingIcon;
+
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
- final newStyle = style ??
+ final newPolicy = policy ??
(constraints.maxWidth > 600
- ? ViewSwitcherStyle.desktop
- : ViewSwitcherStyle.mobile);
+ ? ViewSwitcherPolicy.wide
+ : ViewSwitcherPolicy.narrow);
return Row(
mainAxisSize: MainAxisSize.min,
@@ -41,8 +55,9 @@ class AdwViewSwitcher extends StatelessWidget {
for (final tab in tabs.asMap().entries)
AdwViewSwitcherTab(
data: tab.value,
+ paddingIcon: paddingIcon,
badgeColor: badgeColor,
- style: newStyle,
+ policy: newPolicy,
isSelected: tab.key == currentIndex,
onSelected: currentIndex != tab.key
? () => onViewChanged(tab.key)
diff --git a/lib/src/widgets/adw/view_switcher_tab.dart b/lib/src/widgets/adw/view_switcher_tab.dart
index ce31d6c..17d5ad8 100644
--- a/lib/src/widgets/adw/view_switcher_tab.dart
+++ b/lib/src/widgets/adw/view_switcher_tab.dart
@@ -1,26 +1,38 @@
import 'package:flutter/material.dart';
-import 'package:libadwaita/src/models/models.dart';
-import 'package:libadwaita/src/widgets/widgets.dart';
+import 'package:libadwaita/libadwaita.dart';
class AdwViewSwitcherTab extends StatelessWidget {
const AdwViewSwitcherTab({
Key? key,
required this.data,
- required this.style,
+ required this.policy,
this.badgeColor,
this.isSelected = false,
this.onSelected,
+ this.paddingIcon,
}) : super(key: key);
+ /// The color of the badge at the top right of the tab's icon
final Color? badgeColor;
+
+ /// The of this view switcher tab
final ViewSwitcherData data;
- final ViewSwitcherStyle style;
+
+ /// The Policy of the parent view switcher, either narrow or widget
+ final ViewSwitcherPolicy policy;
+
+ /// Whether this tab is selected or not, defaults to false
final bool isSelected;
+
+ /// Executed when this tab is selected
final VoidCallback? onSelected;
+ /// The Padding for the icon of the view switcher tab
+ final EdgeInsets? paddingIcon;
+
@override
Widget build(BuildContext context) {
- final isDesktop = style == ViewSwitcherStyle.desktop;
+ final isDesktop = policy == ViewSwitcherPolicy.wide;
return AdwButton.flat(
constraints: isDesktop
@@ -39,9 +51,10 @@ class AdwViewSwitcherTab extends StatelessWidget {
Stack(
children: [
Padding(
- padding: isDesktop
- ? const EdgeInsets.only(top: 4, bottom: 4, right: 8)
- : const EdgeInsets.only(top: 3.5, right: 4, left: 4),
+ padding: paddingIcon ??
+ (isDesktop
+ ? const EdgeInsets.only(top: 4, bottom: 4, right: 8)
+ : const EdgeInsets.only(top: 3.5, right: 4, left: 4)),
child: Icon(data.icon, size: 17),
),
if (data.badge != null)
@@ -52,8 +65,7 @@ class AdwViewSwitcherTab extends StatelessWidget {
height: 14,
width: 14,
child: CircleAvatar(
- backgroundColor:
- badgeColor ?? AdwColors.blue.backgroundColor,
+ backgroundColor: badgeColor ?? AdwDefaultColors.blue,
child: Text(
data.badge!,
style: const TextStyle(
@@ -69,13 +81,7 @@ class AdwViewSwitcherTab extends StatelessWidget {
),
if (data.icon != null && data.title != null)
const SizedBox(height: 1.5),
- if (data.title != null)
- Padding(
- padding: isDesktop
- ? const EdgeInsets.symmetric(vertical: 4)
- : EdgeInsets.zero,
- child: Text(data.title!),
- ),
+ if (data.title != null) Text(data.title!),
],
),
);
diff --git a/lib/src/widgets/gtk/popup_menu.dart b/lib/src/widgets/gtk/popup_menu.dart
index 1ef459c..b796bc6 100644
--- a/lib/src/widgets/gtk/popup_menu.dart
+++ b/lib/src/widgets/gtk/popup_menu.dart
@@ -40,6 +40,7 @@ class _AdwPopupMenuState extends State {
setState(() => isActive = true);
showPopover(
context: context,
+ arrowHeight: 14,
shadow: [
BoxShadow(
color: context.borderColor,
diff --git a/pubspec.yaml b/pubspec.yaml
index 0a99791..130f9d0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -7,18 +7,25 @@ environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.17.0"
+platforms:
+ android:
+ ios:
+ linux:
+ macos:
+ web:
+ windows:
+
dependencies:
- dbus: ">=0.6.6 <1.0.0"
+ dbus: ">=0.7.1 <1.0.0"
flutter:
sdk: flutter
flutter_svg: ">=1.0.3 < 2.0.0"
- gsettings: ">=0.2.1 <1.0.0"
+ gsettings: ">=0.2.5 <1.0.0"
package_info_plus: ">=1.3.0 < 2.0.0"
popover_gtk: ">=0.2.6+3 < 1.0.0"
url_launcher: ">=6.0.18 < 7.0.0"
dev_dependencies:
- svg_to_paint: ^1.0.10
very_good_analysis: ^2.4.0
flutter: