--- /dev/null
+#! /bin/bash
+cd lib
+dartfmt -w .
+cd ..
+./Coverage.sh
+
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
- initialRoute: '/role/create',
+ initialRoute: '/role/list',
onGenerateRoute: _getRoute,
);
}
case '/role/list':
page = RoleListPage(BSettings.lastInstance.pageData);
break;
- case '/role/change':
- page = RoleChangePage(BSettings.lastInstance.pageData);
- break;
case '/role/create':
page = RoleCreatePage(BSettings.lastInstance.pageData);
break;
case '/user/list':
page = UserListPage(BSettings.lastInstance.pageData);
break;
- case '/user/change':
- page = UserChangePage(BSettings.lastInstance.pageData);
- break;
case '/user/create':
page = UserCreatePage(BSettings.lastInstance.pageData);
break;
case '/configuration/list':
page = ConfigurationListPage(BSettings.lastInstance.pageData);
break;
- case '/configuration/change':
- page = ConfigurationChangePage(BSettings.lastInstance.pageData);
- break;
case '/configuration/create':
page = ConfigurationCreatePage(BSettings.lastInstance.pageData);
break;
static final regExprOptions = RegExp(r'^(undef)$');
String text;
String name;
+ String toolTip;
final Map<String, dynamic> map;
List<String> options;
ButtonModelType buttonModelType;
+ /// Constructs an instance by parsing the map for some properties.
ButtonModel(SectionModel section, PageModel page, this.map, BaseLogger logger)
: super(section, page, WidgetModelType.button, logger);
+ /// Constructs an instance with all properties given.
+ ButtonModel.direct(
+ SectionModel section,
+ PageModel page,
+ String name,
+ String text,
+ ButtonModelType buttonModelType,
+ List<String> options,
+ this.map,
+ BaseLogger logger)
+ : super(section, page, WidgetModelType.button, logger) {
+ this.name = name;
+ this.text = text;
+ this.toolTip = toolTip;
+ this.options = options;
+ this.buttonModelType = buttonModelType;
+ }
+
/// Dumps a the instance into a [stringBuffer]
StringBuffer dump(StringBuffer stringBuffer) {
stringBuffer.write(
/// Parses the map and stores the data in the instance.
void parse() {
- checkSuperfluousAttributes(
- map, 'buttonType label name options text widgetType'.split(' '));
name = parseString('name', map, required: true);
+ checkSuperfluousAttributes(map,
+ 'buttonType label name options text toolTip widgetType'.split(' '));
text = parseString('text', map);
+ toolTip = parseString('toolTip', map);
buttonModelType =
parseEnum<ButtonModelType>('buttonType', map, ButtonModelType.values);
buttonModelType ??= ButtonModelType.custom;
columnName = parts[1];
}
if (table != null) {
- rc = table.getColumn(columnName);
+ rc = table.columnByName(columnName);
}
return rc;
}
import 'package:dart_bones/dart_bones.dart';
-
import 'button_model.dart';
import 'field_model.dart';
import 'model_base.dart';
/// Represents one screen of the module.
class PageModel extends ModelBase {
- static final regExprOptions = RegExp(r'^(unknown)$');
+ static final regExprOptions = RegExp(r'^(noAutoButton)$');
final ModuleModel module;
final Map<String, dynamic> map;
String name;
PageModelType pageModelType;
List<String> options;
final fields = <FieldModel>[];
- final buttons = <String, ButtonModel>{};
+ final buttons = <ButtonModel>[];
final widgets = <WidgetModel>[];
PageModel(this.module, this.map, BaseLogger logger) : super(logger);
/// Adds a [button] to the [this.buttons].
/// If already defined and error is logged.
void addButton(ButtonModel button) {
- final name = button.name;
- if (buttons.containsKey(name)) {
+ if (buttonByName(button.name, required: false) != null) {
logger.error('button ${button.fullName()} already defined: ' +
- buttons[name].fullName());
+ buttonByName(button.name, required: false).fullName());
} else {
- buttons[name] = button;
+ buttons.add(button);
}
}
+ /// Returns a button named [name] or null if not found.
+ ButtonModel buttonByName(String name, {bool required = true}) {
+ final rc =
+ buttons.firstWhere((item) => item.name == name, orElse: () => null);
+ if (rc == null && required) {
+ logger.error('missing button $name in page ${fullName()}');
+ }
+ return rc;
+ }
+
/// Tests whether the field with [name] is part of the page.
bool hasField(String name) {
final first = fields.firstWhere((element) => element.name == name,
@override
String fullName() => '${module.name}.$name';
- /// Returns a field by [name] or null on error.
- ButtonModel getButton(String name, {bool required = true}) {
- ButtonModel rc;
- if (!buttons.containsKey(name)) {
- if (required) {
- logger.error('missing button $name in page ${fullName()}');
- }
- } else {
- rc = buttons[name];
- }
- return rc;
- }
-
/// Returns a field by [name] or null on error.
FieldModel getField(String name, {bool required = true}) {
final rc = fields.firstWhere((element) => element.name == name,
SectionModel.parseSections(this, null, item, logger);
}
}
+ if (!options.contains('noAutoButton') &&
+ buttonByName('search', required: false) == null) {
+ final section = null;
+ final button = ButtonModel.direct(section, this, 'search', 'Suchen',
+ ButtonModelType.search, [], null, logger);
+ addButton(button);
+ }
checkOptionsByRegExpr(options, regExprOptions);
}
if (!child.containsKey('widgetType')) {
logger.error(
'child $no of "children" does not have "widgetType" in ${fullName()}: '
- '${StringUtils.limitString(child.toString(), 80)}');
+ '${StringUtils.limitString(child.toString(), 80)}');
} else {
final widgetType = StringUtils.stringToEnum<WidgetModelType>(
child['widgetType'].toString(), WidgetModelType.values);
no++;
if (!ModelBase.isMap(item)) {
page.logger.error(
- 'curious item in section list of ${page.fullName()}: ${StringUtils
- .limitString("$item", 80)}');
+ 'curious item in section list of ${page.fullName()}: ${StringUtils.limitString("$item", 80)}');
} else {
final current = SectionModel(no, page, null, item, logger);
current.parse();
import 'package:dart_bones/dart_bones.dart';
import 'package:meta/meta.dart';
+
import 'column_model.dart';
import 'model_base.dart';
import 'model_types.dart';
String name;
List<String> options;
@protected
- final columnMap = <String, ColumnModel>{};
final columns = <ColumnModel>[];
+ ColumnModel primary;
TableModel(this.module, this.map, BaseLogger logger) : super(logger);
/// Adds a [button] to the [this.buttons].
/// If already defined and error is logged.
void addColumn(ColumnModel column) {
- final name = column.name;
- if (columnMap.containsKey(column)) {
- logger.error('column ${column.fullName()} already defined: ' +
- columnMap[name].fullName());
+ if (columnByName(column.name, required: false) != null) {
+ logger.error('column ${column.name} already defined: ' + fullName());
} else {
- columnMap[name] = column;
columns.add(column);
+ if (column.hasOption('primary')) {
+ primary = column;
+ }
+ }
+ }
+
+ /// Returns a column by [name] or null if not found.
+ ColumnModel columnByName(String name, {bool required = true}) {
+ ColumnModel rc = columns.firstWhere((element) => element.name == name,
+ orElse: () => null);
+ if (rc == null && required) {
+ logger.error('missing column $name in table ${fullName()}');
}
+ return rc;
}
/// Dumps the internal structure into a [stringBuffer]
@override
String fullName() => '${module.name}.$name';
- /// Returns a column by [name] or null on error.
- ColumnModel getColumn(String name, {bool required = true}) {
- ColumnModel rc;
- if (!columnMap.containsKey(name)) {
- if (required) {
- logger.error('missing column $name in table ${fullName()}');
- }
- } else {
- rc = columnMap[name];
- }
- return rc;
- }
-
/// Parses the map and stores the data in the instance.
void parse() {
name = parseString('table', map, required: true);
void _addIfMissing(
String name, String label, DataType dataType, List<String> options,
[int size]) {
- if (getColumn(name, required: false) == null) {
+ if (columnByName(name, required: false) == null) {
addColumn(ColumnModel.raw(
name: name,
table: this,
State<StatefulWidget> parent,
String pageName,
BuildContext context,
- ApplicationData applicationData)
+ ApplicationData applicationData,
+ {Function fetchRows})
: super(
formKey,
parent,
Widget build(BuildContext context) {
controller ??= ConfigurationController(
_formKey, this, 'list', context, applicationData);
- filters ??= controller.filterSet(page: 'list');
+ filters ??= controller.filterSet(pageName: 'list');
getRows();
return Scaffold(
appBar: applicationData.appBarBuilder('Rollen'),
class RoleChangePage extends StatefulWidget {
final ApplicationData applicationData;
final logger = Settings().logger;
-
+ final int primaryId;
//RoleChangePageState lastState;
- RoleChangePage(this.applicationData, {Key key}) : super(key: key);
+ RoleChangePage(this.primaryId, this.applicationData, {Key key})
+ : super(key: key);
@override
RoleChangePageState createState() {
- final rc = RoleChangePageState(applicationData);
+ final rc = RoleChangePageState(primaryId, applicationData);
// lastState = rc;
return rc;
}
class RoleChangePageState extends State<RoleChangePage> {
final ApplicationData applicationData;
-
+ final int primaryId;
final GlobalKey<FormState> _formKey =
GlobalKey<FormState>(debugLabel: 'role_change');
RoleController controller;
- RoleChangePageState(this.applicationData);
+ RoleChangePageState(this.primaryId, this.applicationData);
@override
Widget build(BuildContext context) {
- controller = controller ??
- RoleController(_formKey, this, 'change', context, applicationData);
+ if (controller == null) {
+ controller = RoleController(
+ _formKey, this, 'list', context, applicationData,
+ redrawCallback: () => setState(() => null));
+ controller.initialize();
+ }
return Scaffold(
appBar: applicationData.appBarBuilder('Rolle ändern'),
drawer: applicationData.drawerBuilder(context),
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
+ primaryId: primaryId,
));
}
}
import 'package:flutter_bones/flutter_bones.dart';
import '../../model/standard/role_model.dart';
+import 'role_change_page.dart';
import '../../widget/page_controller_bones.dart';
class RoleController extends PageControllerBones {
/// Controller for a page named [pageName].
RoleController(GlobalKey<FormState> formKey, State<StatefulWidget> parent,
- String pageName, BuildContext context, ApplicationData applicationData)
- : super(
- formKey,
- parent,
- RoleModel(Settings().logger),
- pageName,
- context,
- applicationData,
- ) {
+ String pageName, BuildContext context, ApplicationData applicationData,
+ {Function redrawCallback})
+ : super(formKey, parent, RoleModel(Settings().logger), pageName, context,
+ applicationData, redrawCallback) {
moduleModel.parse();
}
+ @override
+ void startChange(int id) {
+ Navigator.push(context,
+ MaterialPageRoute(builder: (context) => RoleChangePage(id, applicationData)));
+ }
}
final GlobalKey<FormState> _formKey =
GlobalKey<FormState>(debugLabel: 'role_list');
- Iterable<dynamic> rows;
+ Iterable<dynamic> rowsDeprecated;
RoleController controller;
FilterSet filters;
@override
Widget build(BuildContext context) {
- controller ??=
- RoleController(_formKey, this, 'list', context, applicationData);
- filters ??= controller.filterSet(page: 'list');
- getRows();
+ if (controller == null) {
+ controller = RoleController(
+ _formKey, this, 'list', context, applicationData,
+ redrawCallback: () => setState(() => null));
+ controller.initialize();
+ }
+ filters ??= controller.filterSet(pageName: 'list');
+ controller.buildRows();
return Scaffold(
appBar: applicationData.appBarBuilder('Rollen'),
drawer: applicationData.drawerBuilder(context),
configuration: applicationData.configuration,
titles: ListForm.stringsToTitles(';Id;Name;Priorität'),
columnNames: 'role_id role_name role_priority'.split(' '),
- rows: rows ?? [],
+ rows: controller.listRows ?? [],
showEditIcon: true,
+ pageController: controller,
buttons: <Widget>[
ButtonBar(alignment: MainAxisAlignment.center, children: [
- RaisedButton(
- child: Text('Suchen'),
- onPressed: () {
- rows = null;
- if (_formKey.currentState.validate()) {
- _formKey.currentState.save();
- getRows();
- }
- },
- ),
+ controller.searchButton(),
RaisedButton(
child: Text('Neue Rolle'),
onPressed: () {
Navigator.pushNamed(context, '/role/create');
+
+ /// Force the redraw on return:
+ controller.listRows = null;
},
),
]),
),
);
}
-
- void getRows() {
- final persistence = applicationData.persistence;
- final namePattern = filters.valueOf('role_name') ?? '';
- persistence.list(module: 'role', params: {
- ':role_name': namePattern.replaceAll('*', '%') + '%'
- }).then((list) {
- if (rows == null) {
- rows = list;
- setState(() {});
- }
- }, onError: (error) {
- applicationData.logger.error('cannot retrieve role list: $error');
- });
- }
}
Widget build(BuildContext context) {
controller ??=
UserController(_formKey, this, 'list', context, applicationData);
- filters ??= controller.filterSet(page: 'list');
+ filters ??= controller.filterSet(pageName: 'list');
getRows();
return Scaffold(
appBar: applicationData.appBarBuilder('Rollen'),
/// flutter_bones specific widgets: [CheckboxListTileBone],
/// [DropDownButtonFormBone], [RaisedButtonBone], [TextFormFieldBone]
abstract class CallbackControllerBones {
+ /// Prepares the rows shown in the list page
+ void buildRows();
+
List<String> comboboxTexts(
String customString, CallbackControllerBones controller);
FormFieldValidator<String> getValidator(
String customString, CallbackControllerBones controller);
+
+ /// Handles the tap event in the table of the list page.
+ void onEditTap(
+ String customString, CallbackControllerBones controller, Map row);
+
+ /// Rebuilds the view of the page.
+ void redraw();
+
+ /// Returns a standard search button for the list page.
+ Widget searchButton();
+
+ /// Starts the change page to edit the record with primary key [id].
+ void startChange(int id);
+
+ /// Returns the field value of field named [fieldName] or null if not found.
+ dynamic valueOf(String fieldName);
}
--- /dev/null
+import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
+import 'page_controller_bones.dart';
+
+class CheckboxFormField extends FormField<bool> {
+ CheckboxFormField({
+ /// properties of FormField:
+ Key keyFormField,
+ FormFieldSetter<bool> onSaved,
+ FormFieldValidator<bool> validator,
+ bool initialValue = false,
+ AutovalidateMode autovalidateMode,
+ // properties of CheckboxListTile:
+ Key keyCheckbox,
+ Widget title,
+ }) : super(
+ key: keyFormField,
+ onSaved: onSaved,
+ validator: validator,
+ initialValue: initialValue,
+ builder: (FormFieldState<bool> state) {
+ return CheckboxListTile(
+ key: keyCheckbox,
+ dense: state.hasError,
+ title: title,
+ value: state.value,
+ onChanged: state.didChange,
+ subtitle: state.hasError
+ ? Builder(
+ builder: (BuildContext context) => Text(
+ state.errorText,
+ style: TextStyle(color: Theme.of(context).errorColor),
+ ),
+ )
+ : null,
+ controlAffinity: ListTileControlAffinity.leading,
+ );
+ },
+ autovalidateMode: autovalidateMode);
+/**
+ * Key? key,
+ required this.value,
+ required this.onChanged,
+ this.activeColor,
+ this.checkColor,
+ this.tileColor,
+ this.title,
+ this.subtitle,
+ this.isThreeLine = false,
+ this.dense,
+ this.secondary,
+ this.selected = false,
+ this.controlAffinity = ListTileControlAffinity.platform,
+ this.autofocus = false,
+ this.contentPadding,
+ this.tristate = false,
+ this.shape,
+
+ * Key? key,
+ required this.builder,
+ this.onSaved,
+ this.validator,
+ this.initialValue,
+ @Deprecated(
+ 'Use autoValidateMode parameter which provides more specific '
+ 'behavior related to auto validation. '
+ 'This feature was deprecated after v1.19.0.'
+ )
+ this.autovalidate = false,
+ this.enabled = true,
+ AutovalidateMode? autovalidateMode,
+
+ */
+}
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
-import 'package:flutter_bones/src/widget/page_controller_bones.dart';
+import 'page_controller_bones.dart';
/// Implements a [Checkbox] with "outsourced" callbacks:
/// [customString] a string mostly used for a name needed in the [callbackController]
FormFieldValidator<T> validator,
AutovalidateMode autovalidateMode,
}) : super(
- key: key,
- items: items,
- selectedItemBuilder: callbackController.getOnSelectedItemBuilder(
- customString, callbackController),
- value: value,
- hint: hint,
- disabledHint: disabledHint,
- onChanged: callbackController.getOnChangedCombobox<T>(
- customString, callbackController),
- onTap: callbackController.getOnTap(customString, callbackController),
- elevation: elevation,
- style: style,
- icon: icon,
- iconDisabledColor: iconDisabledColor,
- iconEnabledColor: iconEnabledColor,
- iconSize: iconSize,
- isDense: isDense,
- isExpanded: isExpanded,
- itemHeight: itemHeight,
+ key: key,
+ items: items,
+ selectedItemBuilder: callbackController.getOnSelectedItemBuilder(
+ customString, callbackController),
+ value: value,
+ hint: hint,
+ disabledHint: disabledHint,
+ onChanged: callbackController.getOnChangedCombobox<T>(
+ customString, callbackController),
+ onTap: callbackController.getOnTap(customString, callbackController),
+ elevation: elevation,
+ style: style,
+ icon: icon,
+ iconDisabledColor: iconDisabledColor,
+ iconEnabledColor: iconEnabledColor,
+ iconSize: iconSize,
+ isDense: isDense,
+ isExpanded: isExpanded,
+ itemHeight: itemHeight,
focusColor: focusColor,
focusNode: focusNode,
autofocus: autofocus,
@required Key key,
@required PageControllerBones pageController,
@required BaseConfiguration configuration,
+ int primaryId,
}) {
final padding =
configuration.asFloat('form.card.padding', defaultValue: 16.0);
final widgets = pageController.getWidgets();
+ if (primaryId != null){
+ pageController.fetchData(primaryId);
+ }
return Form(
key: key,
child: Card(
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_bones/src/widget/page_controller_bones.dart';
import '../helper/string_helper.dart';
import 'filter_set.dart';
+import 'page_controller_bones.dart';
typedef Function OnEditTap(Map<String, dynamic> row, int index);
static Widget table({
@required List<Widget> titles,
@required List<String> columnNames,
+ @required PageControllerBones controller,
@required Iterable<dynamic> rows,
bool showEditIcon = false,
int sortIndex,
rows: rows.map((row) {
final cells = <DataCell>[];
if (showEditIcon) {
- cells.add(DataCell(SizedBox(width: 1), showEditIcon: true));
+ cells.add(
+ DataCell(SizedBox(width: 1), showEditIcon: true, onTap: () {
+ controller.onEditTap(customString, controller, row);
+ }));
}
for (var key in columnNames) {
cells.add(DataCell(
Text(StringHelper.asString(row[key])),
- onTap: () => tableCallbackController.getOnEditTap(
- customString, tableCallbackController, row),
));
}
return DataRow(cells: cells);
@required List<String> columnNames,
@required Iterable<dynamic> rows,
bool showEditIcon = false,
- TableCallbackController tableCallbackController,
+ PageControllerBones pageController,
@required BaseConfiguration configuration,
String customString}) {
final padding =
columnNames: columnNames,
rows: rows,
showEditIcon: showEditIcon,
- tableCallbackController: tableCallbackController,
+ controller: pageController,
customString: customString,
)
])),
import 'package:flutter_bones/flutter_bones.dart';
import 'package:flutter_bones/src/widget/widget_list.dart';
+import '../model/column_model.dart';
import '../model/module_model.dart';
import '../page/application_data.dart';
import 'callback_controller_bones.dart';
final ModuleModel moduleModel;
String primaryColumn;
WidgetList widgetList;
-
+ final Function redrawCallback;
+ bool needsRedraw;
//WidgetList changeWidgets;
final GlobalKey<FormState> globalKey;
final String pageName;
final ApplicationData applicationData;
State parent;
final BuildContext context;
+ Iterable listRows;
PageControllerBones(this.globalKey, this.parent, this.moduleModel,
- this.pageName, this.context, this.applicationData) {}
+ this.pageName, this.context, this.applicationData,
+ [this.redrawCallback]);
+ @override
+ void buildRows() {
+ needsRedraw = true;
+ final persistence = applicationData.persistence;
+ final params = buildSqlParams() ?? {};
+ persistence.list(module: 'role', params: params).then((list) {
+ if (listRows == null) {
+ listRows = list;
+ redraw();
+ }
+ }, onError: (error) {
+ applicationData.logger.error('cannot retrieve role list: $error');
+ });
+ }
- /// Initializes the controller when the instance is complete constructed,
- /// e.g. ModuleModel.parse() is called.
- /// This method must be called early after the constructor.
- void initialize() {
- widgetList =
- WidgetList('${moduleModel.fullName()}.widgets', moduleModel.logger);
- page = moduleModel.pageByName(pageName);
- page.fields.forEach((model) {
- widgetList.addWidget(
- model.name, View(moduleModel.logger).modelToWidget(model, this));
+ /// Builds the SQL parameters of all members of the [widgets].
+ Map<String, String> buildSqlParams() {
+ final rc = <String, String>{};
+ page.fields.forEach((element) {
+ if (element.filterType != null) {
+ dynamic value = element.value;
+ DataType dataType = element.dataType;
+ String name = element.name;
+ String operator;
+ if (element.filterType == FilterType.pattern) {
+ if (value == null || value.isEmpty) {
+ value = '%';
+ } else if (value is String) {
+ value = value.replaceAll('*', '%') + '%';
+ }
+ }
+ if (name != null && dataType != null) {
+ rc[':$name'] = StringHelper.asDatabaseString(value, dataType);
+ }
+ }
});
+ return rc;
}
@override
return [];
}
- FilterSet filterSet({@required String page}) {
+ /// Gets the data from the database using the [primaryId].
+ fetchData(int primaryId) async {
+ applicationData.persistence
+ .record(module: moduleModel.name, id: primaryId)
+ .then((row) {
+ page.fields.forEach((model) {
+ model.value = row[model.name];
+ });
+ needsRedraw = true;
+ redraw();
+ });
+ }
+
+ FilterSet filterSet({@required String pageName}) {
final rc = FilterSet(globalKey, parent, this, moduleModel.logger);
moduleModel
- .pageByName(page)
+ .pageByName(pageName)
.fields
.where((element) => element.filterType != null)
.forEach((element) {
return rc;
}
+ @override
+ ApplicationData getApplicationData() {
+ return applicationData;
+ }
+
@override
BuildContext getContext() {
return context;
}
@override
- getOnHighlightChanged(String customString,
- CallbackControllerBones controller) {
+ getOnHighlightChanged(
+ String customString, CallbackControllerBones controller) {
return null;
}
@override
getOnPressed(String customString, CallbackControllerBones controller) {
var rc;
- if (customString == 'store') {
+ if (customString == 'search') {
+ rc = () {
+ if (globalKey.currentState.validate()) {
+ globalKey.currentState.save();
+ listRows = null;
+ buildRows();
+ // controller.fetchListRows();
+ }
+ };
+ } else if (customString == 'store') {
rc = () {
if (globalKey.currentState.validate()) {
globalKey.currentState.save();
final params = widgetList.buildSqlParams(this);
PageModelType pageType =
- moduleModel
- .pageByName(pageName)
- .pageModelType;
+ moduleModel.pageByName(pageName).pageModelType;
switch (pageType) {
case PageModelType.create:
applicationData.persistence
.insert(module: moduleModel.name, data: params);
+ Navigator.pop(controller.getContext());
break;
case PageModelType.change:
applicationData.persistence
.update(module: moduleModel.name, data: params);
+ Navigator.pop(controller.getContext());
break;
default:
moduleModel.logger
@override
getOnSaved(String customString, CallbackControllerBones controller) {
final rc = (input) {
- final page = moduleModel.pageByName(pageName);
FieldModel model = page.getField(customString);
model.value = StringHelper.fromString(input, model.dataType);
};
}
@override
- getOnSelectedItemBuilder(String customString,
- CallbackControllerBones controller) {
+ getOnSelectedItemBuilder(
+ String customString, CallbackControllerBones controller) {
return null;
}
return null;
}
- @override
- TextEditingController getTextEditingController(String customString,
- CallbackControllerBones controller) {
- return null;
- }
-
@override
getValidator(String customString, CallbackControllerBones controller) {
return null;
///
List<Widget> getWidgets() {
List<Widget> rc;
- final page = moduleModel.pageByName(pageName);
rc = View(moduleModel.logger).modelsToWidgets(page.fields, this);
return rc ?? [];
}
+ /// Initializes the controller when the instance is complete constructed,
+ /// e.g. ModuleModel.parse() is called.
+ /// This method must be called early after the constructor.
+ void initialize() {
+ widgetList =
+ WidgetList('${moduleModel.fullName()}.widgets', moduleModel.logger);
+ page = moduleModel.pageByName(pageName);
+ page.fields.forEach((model) {
+ widgetList.addWidget(
+ model.name, View(moduleModel.logger).modelToWidget(model, this));
+ });
+ }
+
@override
- ApplicationData getApplicationData() {
- return applicationData;
+ onEditTap(String customString, CallbackControllerBones controller, Map row) {
+ ColumnModel primary = moduleModel.mainTable().primary;
+ final id = row[primary.name];
+ controller.startChange(id);
+ }
+
+ @override
+ void redraw() {
+ if (redrawCallback == null) {
+ moduleModel.logger.error(
+ 'not overridden: fetchListRows() in ${moduleModel.widgetName()}.$pageName');
+ } else {
+ if (needsRedraw) {
+ needsRedraw = false;
+ redrawCallback();
+ }
+ }
+ }
+
+ @override
+ Widget searchButton() {
+ final rc = View(moduleModel.logger)
+ .modelToWidget(page.buttonByName('search'), this);
+ return rc;
+ }
+
+ @override
+ void startChange(int id) {
+ moduleModel.logger.error(
+ 'missing override of startChange() in ${moduleModel.fullName()}');
+ }
+
+ @override
+ dynamic valueOf(String fieldName) {
+ final rc = page.getField(fieldName)?.value;
+ return rc;
}
}
final String customString;
final CallbackControllerBones callbackController;
- TextFormFieldBone(this.customString,
- this.callbackController, {
- Key key,
- TextEditingController controller,
- String initialValue,
- FocusNode focusNode,
- InputDecoration decoration = const InputDecoration(),
- TextInputType keyboardType,
- TextCapitalization textCapitalization = TextCapitalization.none,
- TextInputAction textInputAction,
- TextStyle style,
- StrutStyle strutStyle,
- TextDirection textDirection,
- TextAlign textAlign = TextAlign.start,
- TextAlignVertical textAlignVertical,
- bool autofocus = false,
- bool readOnly = false,
- ToolbarOptions toolbarOptions,
- bool showCursor,
- String obscuringCharacter = '•',
- bool obscureText = false,
- bool autocorrect = true,
- SmartDashesType smartDashesType,
- SmartQuotesType smartQuotesType,
- bool enableSuggestions = true,
- bool maxLengthEnforced = true,
- int maxLines = 1,
- int minLines,
+ TextFormFieldBone(
+ this.customString,
+ this.callbackController, {
+ Key key,
+ TextEditingController controller,
+ String initialValue,
+ FocusNode focusNode,
+ InputDecoration decoration = const InputDecoration(),
+ TextInputType keyboardType,
+ TextCapitalization textCapitalization = TextCapitalization.none,
+ TextInputAction textInputAction,
+ TextStyle style,
+ StrutStyle strutStyle,
+ TextDirection textDirection,
+ TextAlign textAlign = TextAlign.start,
+ TextAlignVertical textAlignVertical,
+ bool autofocus = false,
+ bool readOnly = false,
+ ToolbarOptions toolbarOptions,
+ bool showCursor,
+ String obscuringCharacter = '•',
+ bool obscureText = false,
+ bool autocorrect = true,
+ SmartDashesType smartDashesType,
+ SmartQuotesType smartQuotesType,
+ bool enableSuggestions = true,
+ bool maxLengthEnforced = true,
+ int maxLines = 1,
+ int minLines,
bool expands = false,
int maxLength,
List<TextInputFormatter> inputFormatters,
/// Creates a button from the [controller].
Widget button(ButtonModel model, CallbackControllerBones controller) {
- final rc = RaisedButtonBone(
+ Widget rc;
+ rc = RaisedButtonBone(
model.name,
controller,
child: Text(model.text),
);
+ if (model.toolTip != null) {
+ rc = Tooltip(message: model.toolTip, child: rc);
+ }
return rc;
}
return rc;
}
+ /// Creates a checkbox from the [model].
+ Widget checkbox(FieldModel model, CallbackControllerBones controller) {
+ final tristate = model.hasOption('undef');
+ final rc = toolTip(
+ CheckboxListTileBone(model.name, controller,
+ value: tristate ? model.value : model.value ?? false,
+ tristate: tristate,
+ title: Text(model.label),
+ selected: model.value ?? false),
+ model);
+ return rc;
+ }
+
/// Creates a combobox via the [controller].
Widget combobox<T>(FieldModel model, CallbackControllerBones controller) {
final texts = controller.comboboxTexts(model.name, controller);
return rc;
}
- /// Creates a checkbox from the [model].
- Widget checkbox(FieldModel model, CallbackControllerBones controller) {
- final tristate = model.hasOption('undef');
- final rc = toolTip(
- CheckboxListTileBone(model.name, controller,
- value: tristate ? model.value : model.value ?? false,
- tristate: tristate,
- title: Text(model.label),
- selected: model.value ?? false),
- model);
- return rc;
- }
-
Widget dbReference(
DbReferenceModel model, CallbackControllerBones controller) {
var rc;
return rc;
}
+ /// Converts a list of [models] into a list of [Widget]s.
+ List<Widget> modelsToWidgets(
+ List<WidgetModel> models, CallbackControllerBones controller) {
+ final rc = <Widget>[];
+ for (var model in models) {
+ final widget = modelToWidget(model, controller);
+ if (widget != null) {
+ rc.add(widget);
+ }
+ }
+ return rc;
+ }
+
+ /// Converts a [model] into a [Widget].
+ Widget modelToWidget(WidgetModel model, CallbackControllerBones controller) {
+ Widget rc;
+ switch (model?.widgetModelType) {
+ case WidgetModelType.textField:
+ rc = textField(model, controller);
+ break;
+ case WidgetModelType.button:
+ rc = button(model, controller);
+ break;
+ case WidgetModelType.emptyLine:
+ rc = emptyLine(model);
+ break;
+ case WidgetModelType.text:
+ rc = text(model);
+ break;
+ case WidgetModelType.checkbox:
+ rc = checkbox(model, controller);
+ break;
+ case WidgetModelType.combobox:
+ rc = text(model);
+ break;
+ case WidgetModelType.image:
+ rc = image(model);
+ break;
+ case WidgetModelType.section:
+ rc = section(model);
+ break;
+ case WidgetModelType.dbReference:
+ rc = dbReference(model, controller);
+ break;
+ case WidgetModelType.allDbFields:
+ break;
+ case WidgetModelType.table:
+ case WidgetModelType.column:
+ logger.error('not allowed in section: ${model.fullName()}');
+ break;
+ }
+ return rc;
+ }
+
/// Creates a section from the [model].
Widget section(WidgetModel model) {
var rc;
{SectionModel model, CallbackControllerBones controller, Key formKey}) {
assert(formKey != null);
final padding =
- widgetConfiguration.asFloat('form.card.padding', defaultValue: 16.0);
+ widgetConfiguration.asFloat('form.card.padding', defaultValue: 16.0);
final children = modelsToWidgets(model.children, controller);
final buttons = buttonList(model.buttons, controller);
final rc = Form(
}
return rc;
}
-
- /// Converts a list of [models] into a list of [Widget]s.
- List<Widget> modelsToWidgets(List<WidgetModel> models,
- CallbackControllerBones controller) {
- final rc = <Widget>[];
- for (var model in models) {
- final widget = modelToWidget(model, controller);
- if (widget != null) {
- rc.add(widget);
- }
- }
- return rc;
- }
-
- /// Converts a [model] into a [Widget].
- Widget modelToWidget(WidgetModel model, CallbackControllerBones controller) {
- Widget rc;
- switch (model.widgetModelType) {
- case WidgetModelType.textField:
- rc = textField(model, controller);
- break;
- case WidgetModelType.button:
- rc = button(model, controller);
- break;
- case WidgetModelType.emptyLine:
- rc = emptyLine(model);
- break;
- case WidgetModelType.text:
- rc = text(model);
- break;
- case WidgetModelType.checkbox:
- rc = checkbox(model, controller);
- break;
- case WidgetModelType.combobox:
- rc = text(model);
- break;
- case WidgetModelType.image:
- rc = image(model);
- break;
- case WidgetModelType.section:
- rc = section(model);
- break;
- case WidgetModelType.dbReference:
- rc = dbReference(model, controller);
- break;
- case WidgetModelType.allDbFields:
- break;
- case WidgetModelType.table:
- case WidgetModelType.column:
- logger.error('not allowed in section: ${model.fullName()}');
- break;
- }
- return rc;
- }
}
import 'package:dart_bones/dart_bones.dart';
-import 'package:flutter/material.dart';
import 'package:flutter_bones/flutter_bones.dart';
import 'package:intl/intl.dart';
import 'package:test/test.dart';
button buttonStore: text: options: null
] # create.simpleForm1
''');
- final userField = table.getColumn('user_id');
+ final userField = table.columnByName('user_id');
expect(userField, isNotNull);
expect(userField.widgetName(), 'user_id');
expect(userField.fullName(), equals('user.user_id'));
expect(userField.fullName(), equals('create.user'));
expect(userField.page.fullName(), equals(page.fullName()));
expect(userField.section, isNotNull);
- final button = page.getButton('buttonStore');
+ final button = page.buttonByName('buttonStore');
expect(button, isNotNull);
expect(button.section, equals(userField.section));
expect(button.fullName(), 'simpleForm1.buttonStore');