Tuesday, March 30, 2021

Edward Lance Lorilla

Edward Lance Lorilla


【VISUAL VB.NET】Color Image to Grayscale

Posted: 30 Mar 2021 03:51 AM PDT

Public Class Form1
Private bit As Bitmap
Private file As Image
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If PictureBox1.Image Is Nothing Then
Return
End If
PictureBox1.Image = bit
For x As Integer = 0 To bit.Width - 1
For y As Integer = 0 To bit.Height - 1
Dim originalColor As Color = bit.GetPixel(x, y)
Dim grayScale As Integer = CInt(Math.Truncate((originalColor.R * 0.3) + (originalColor.G * 0.59) + (originalColor.B * 0.11)))
Dim newColor As Color = Color.FromArgb(grayScale, grayScale, grayScale)
bit.SetPixel(x, y, newColor)
Next
Next
PictureBox1.Image = bit
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
OpenFileDialog1.FileName = ""
Dim dr As DialogResult = OpenFileDialog1.ShowDialog()
If dr = DialogResult.OK Then
file = Image.FromFile(OpenFileDialog1.FileName.ToString())
PictureBox1.Image = file
bit = New Bitmap(OpenFileDialog1.FileName.ToString())
End If
End Sub
End Class
view raw Form1.vb hosted with ❤ by GitHub

【Vuejs】search keyword highlighting

Posted: 29 Mar 2021 10:18 PM PDT

<template id="highlight">
<div v-if="_changeText" >
<span :class="item.deep ? 'green' : '' " v-for="(item, index) in highlightList" :key="index">{{ item.val }}</span>
</div>
</template>
<div id="app">
<div class="search_box">
<input type="text" @input="searchValue" class="search"/>
</div>
<div class="list_li" v-for="(item, index) in filterList" :key="index" :data-index="index" @click="pitchOn">
<highlight :text="item" :search="value" />
</div>
</div>
view raw index.html hosted with ❤ by GitHub
Vue.component('highlight',{
/**
* Component attribute list
*/
template:'#highlight',
props: {
text:String,
search:{
type:String,
}
},
/**
* Initial data of the component
*/
data(){
return{
highlightList:[],//Processed data
}
},
mounted(){
console.log(this.text)
},
computed:{
_changeText(){
if(this.search.length> 0 && this.text.indexOf(this.search)> -1){
this._filterHighlight(this.text, this.search);
}
return this.text
},
},
/**
* List of component methods
*/
methods: {
_filterHighlight(text, key){
let textList = text.split("");
let keyList = key.split("");
let list = [];
for(let i = 0;i <textList.length;i++){
let obj = {
deep:false,
val:textList[i]
}
list.push(obj);
};
for(let k = 0;k <keyList.length;k++){
list.forEach(item => {
if(item.val === keyList[k]){
item.deep = true;
}
})
}
this.highlightList = list
},
}
})
new Vue({
data: {
value:"",
list:[
'lorem',
'ipsum'
],
filterList:[],//filtered
},
methods:{
searchValue(e){
let val = e.target.value;
this.value = val
if(val.length> 0){
this.filterList =[]
let arr = [];
for(let i = 0;i <this.list.length;i++){
if(this.list[i].indexOf(val)> -1){
arr.push(this.list[i])
}
}
this.filterList = arr
}else{
this.filterList = []
}
},
// selected
pitchOn(e){
let index = e.currentTarget.dataset.index;
console.log({ title: `Selected: ${this.filterList[index]}`, icon: "none" });
},
}
}).$mount("#app")
view raw script.js hosted with ❤ by GitHub
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
view raw scripts hosted with ❤ by GitHub
.green{
color: #19C29C;
}
view raw style.css hosted with ❤ by GitHub

【PYTHON OPENCV】Handwritten digits recognition using KNN and raw pixels as features and varying keys

Posted: 29 Mar 2021 07:20 PM PDT

"""
Handwritten digits recognition using KNN and raw pixels as features and varying keys"""
# Import required packages:
import cv2
import numpy as np
import matplotlib.pyplot as plt
from collections import defaultdict
# Constants:
SIZE_IMAGE = 20
NUMBER_CLASSES = 10
def load_digits_and_labels(big_image):
"""Returns all the digits from the 'big' image and creates the corresponding labels for each image"""
# Load the 'big' image containing all the digits:
digits_img = cv2.imread(big_image, 0)
# Get all the digit images from the 'big' image:
number_rows = digits_img.shape[1] / SIZE_IMAGE
rows = np.vsplit(digits_img, digits_img.shape[0] / SIZE_IMAGE)
digits = []
for row in rows:
row_cells = np.hsplit(row, number_rows)
for digit in row_cells:
digits.append(digit)
digits = np.array(digits)
# Create the labels for each image:
labels = np.repeat(np.arange(NUMBER_CLASSES), len(digits) / NUMBER_CLASSES)
return digits, labels
def get_accuracy(predictions, labels):
"""Returns the accuracy based on the coincidences between predictions and labels"""
accuracy = (np.squeeze(predictions) == labels).mean()
return accuracy * 100
def raw_pixels(img):
"""Return raw pixels as feature from the image"""
return img.flatten()
# Load all the digits and the corresponding labels:
digits, labels = load_digits_and_labels('digits.png')
# Shuffle data
# Constructs a random number generator:
rand = np.random.RandomState(1234)
# Randomly permute the sequence:
shuffle = rand.permutation(len(digits))
digits, labels = digits[shuffle], labels[shuffle]
# Compute the descriptors for all the images.
# In this case, the raw pixels are the feature descriptors
raw_descriptors = []
for img in digits:
raw_descriptors.append(np.float32(raw_pixels(img)))
raw_descriptors = np.squeeze(raw_descriptors)
# At this point we split the data into training and testing (50% for each one):
partition = int(0.5 * len(raw_descriptors))
raw_descriptors_train, raw_descriptors_test = np.split(raw_descriptors, [partition])
labels_train, labels_test = np.split(labels, [partition])
# Train the KNN model:
print('Training KNN model - raw pixels as features')
knn = cv2.ml.KNearest_create()
knn.train(raw_descriptors_train, cv2.ml.ROW_SAMPLE, labels_train)
# Create a dictionary to store the accuracy when testing:
results = defaultdict(list)
for k in np.arange(1, 10):
ret, result, neighbours, dist = knn.findNearest(raw_descriptors_test, k)
acc = get_accuracy(result, labels_test)
print(" {}".format("%.2f" % acc))
results['50'].append(acc)
# Show all results using matplotlib capabilities:
# Create the dimensions of the figure and set title:
fig = plt.figure(figsize=(12, 5))
plt.suptitle("k-NN handwritten digits recognition", fontsize=14, fontweight='bold')
fig.patch.set_facecolor('silver')
ax = plt.subplot(1, 1, 1)
ax.set_xlim(0, 10)
dim = np.arange(1, 10)
for key in results:
ax.plot(dim, results[key], linestyle='--', marker='o', label="50%")
plt.legend(loc='upper left', title="% training")
plt.title('Accuracy of the K-NN model varying k')
plt.xlabel("number of k")
plt.ylabel("accuracy")
plt.show()

【WebGL】 Canvas Context

Posted: 29 Mar 2021 03:46 AM PDT

<canvas id="canvas" width="1200" height="600"></canvas>
<script id="vertex-data" type="not-javascript">
attribute vec4 vertex_points;
void main() {
gl_Position = vertex_points;
}
</script>
<script id="fragment-data" type="not-javascript">
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0, 0, 1.0);
}
</script>
view raw index.html hosted with ❤ by GitHub
/* Create a WebGL Context */
const canvas = document.querySelector("#canvas");
const gl = canvas.getContext('webgl');
if (!gl) {
console.log('WebGL unavailable');
} else {
console.log('WebGL is good to go');
}
console.log(gl.drawingBufferWidth);
console.log(gl.drawingBufferHeight);
console.log(gl);
/* Define and Store the Geometry */
// Define the points in the scene
const coordinates = [
-0.7, 0.7,
0.7, 0.7,
-0.7, 0,
0.7, 0,
];
// Create an empty buffer object to store the vertex points
const pointsBuffer = gl.createBuffer();
// Connect the empty buffer object to the GL context
gl.bindBuffer(gl.ARRAY_BUFFER, pointsBuffer);
// Load the vertices into the GL's connected buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(coordinates), gl.STATIC_DRAW);
/* Shaders */
// Create a variable to store the data for our vertex shader
const vsSource = document.querySelector("#vertex-data").text;
// Create a varialble to store the data from our fragment shader
const fsSource = document.querySelector("#fragment-data").text;
// Compile the shaders into little programs
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);
// Create a GL program to connect the shaders to the GL context
const program = gl.createProgram();
// Attach the shaders to the GL context through the program
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// Create shader executables to run on the GPU
gl.linkProgram(program);
// Define the active program defining what the GPU will draw
gl.useProgram(program);
/*Connect the attribute with the vertex shader */
// Locate the attribute from the vertex shader source in the program
const pointsAttributeLocation = gl.getAttribLocation(program, "vertex_points");
// Connect the attribute to the points data currently in the buffer object
gl.vertexAttribPointer(pointsAttributeLocation, 2, gl.FLOAT, false, 0, 0);
// Send the points data to the GPU
gl.enableVertexAttribArray(pointsAttributeLocation);
/*Drawing */
// Clear the canvas
gl.clearColor(0, 0, 0, 0);
// Clear the GL context's color buffer for a fresh paint
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw the points on the screen
const mode = gl.TRIANGLE_STRIP;
const first = 0;
const count = 4;
gl.drawArrays(mode, first, count);
view raw script.js hosted with ❤ by GitHub
canvas {
width: 100vw;
height: 100vh;
display: block;
}
view raw style.css hosted with ❤ by GitHub

【VISUAL VB.NET】Check Driver

Posted: 28 Mar 2021 09:32 PM PDT

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Imports System.Windows.Forms
Imports System.Management
' make sure that using System.Diagnostics; is included
Imports System.Diagnostics
' make sure that using System.Security.Principal; is included
Imports System.Security.Principal
Public Class Form1
Private Sub GetDrivers()
Dim query As New System.Management.SelectQuery("Win32_SystemDriver")
Dim searcher As New System.Management.ManagementObjectSearcher(query)
ListBox1.Items.Clear()
For Each ManageObject As System.Management.ManagementObject In searcher.[Get]()
ListBox1.Items.Add((((("Name: " + ManageObject("Name") & " StartMode: ") + ManageObject("StartMode") & " State: ") + ManageObject("State") & " Description: ") + ManageObject("Description") & " PathName: ") + ManageObject("PathName"))
Next
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GetDrivers()
End Sub
End Class
view raw Form1.vb hosted with ❤ by GitHub

【PYTHON OPENCV】Handwritten digits recognition using KNN and raw pixels as features

Posted: 28 Mar 2021 05:57 PM PDT

"""
Handwritten digits recognition using KNN and raw pixels as features
"""
# Import required packages:
import cv2
import numpy as np
# Constants:
SIZE_IMAGE = 20
NUMBER_CLASSES = 10
def load_digits_and_labels(big_image):
"""Returns all the digits from the 'big' image and creates the corresponding labels for each image"""
# Load the 'big' image containing all the digits:
digits_img = cv2.imread(big_image, 0)
# Get all the digit images from the 'big' image:
number_rows = digits_img.shape[1] / SIZE_IMAGE
rows = np.vsplit(digits_img, digits_img.shape[0] / SIZE_IMAGE)
digits = []
for row in rows:
row_cells = np.hsplit(row, number_rows)
for digit in row_cells:
digits.append(digit)
digits = np.array(digits)
# Create the labels for each image:
labels = np.repeat(np.arange(NUMBER_CLASSES), len(digits) / NUMBER_CLASSES)
return digits, labels
def get_accuracy(predictions, labels):
"""Returns the accuracy based on the coincidences between predictions and labels"""
accuracy = (np.squeeze(predictions) == labels).mean()
return accuracy * 100
def raw_pixels(img):
"""Return raw pixels as feature from the image"""
return img.flatten()
# Load all the digits and the corresponding labels:
digits, labels = load_digits_and_labels('digits.png')
# Shuffle data
# Constructs a random number generator:
rand = np.random.RandomState(1234)
# Randomly permute the sequence:
shuffle = rand.permutation(len(digits))
digits, labels = digits[shuffle], labels[shuffle]
# Compute the descriptors for all the images.
# In this case, the raw pixels are the feature descriptors
raw_descriptors = []
for img in digits:
raw_descriptors.append(np.float32(raw_pixels(img)))
raw_descriptors = np.squeeze(raw_descriptors)
# At this point we split the data into training and testing (50% for each one):
partition = int(0.5 * len(raw_descriptors))
raw_descriptors_train, raw_descriptors_test = np.split(raw_descriptors, [partition])
labels_train, labels_test = np.split(labels, [partition])
# Train the KNN model:
print('Training KNN model - raw pixels as features')
knn = cv2.ml.KNearest_create()
knn.train(raw_descriptors_train, cv2.ml.ROW_SAMPLE, labels_train)
# Test the created model:
k = 5
ret, result, neighbours, dist = knn.findNearest(raw_descriptors_test, k)
# Compute the accuracy:
acc = get_accuracy(result, labels_test)
print("Accuracy: {}".format(acc))

【FLUTTER ANDROID STUDIO and IOS】Appointment System with SQLite

Posted: 28 Mar 2021 05:37 PM PDT

import "package:flutter/material.dart";
import "package:scoped_model/scoped_model.dart";
import "AppointmentsDBWorker.dart";
import "AppointmentsList.dart";
import "AppointmentsEntry.dart";
import "AppointmentsModel.dart" show AppointmentsModel, appointmentsModel;
class Appointments extends StatelessWidget {
Appointments() {
print("## Appointments.constructor");
appointmentsModel.loadData("appointments", AppointmentsDBWorker.db);
}
Widget build(BuildContext inContext) {
print("## Appointments.build()");
return ScopedModel<AppointmentsModel>(
model: appointmentsModel,
child: ScopedModelDescendant<AppointmentsModel>(
builder: (BuildContext inContext, Widget inChild,
AppointmentsModel inModel) {
return IndexedStack(
index: inModel.stackIndex,
children: [
AppointmentsList(),
AppointmentsEntry()
]
);
}
)
);
}
}
import "package:path/path.dart";
import "package:sqflite/sqflite.dart";
import "../utils.dart" as utils;
import "AppointmentsModel.dart";
class AppointmentsDBWorker {
AppointmentsDBWorker._();
static final AppointmentsDBWorker db = AppointmentsDBWorker._();
Database _db;
Future get database async {
if (_db == null) {
_db = await init();
}
print("## appointments AppointmentsDBWorker.get-database(): _db = $_db");
return _db;
}
Future<Database> init() async {
String path = join(utils.docsDir.path, "appointments.db");
print("## appointments AppointmentsDBWorker.init(): path = $path");
Database db = await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database inDB, int inVersion) async {
await inDB.execute(
"CREATE TABLE IF NOT EXISTS appointments ("
"id INTEGER PRIMARY KEY,"
"title TEXT,"
"description TEXT,"
"apptDate TEXT,"
"apptTime TEXT"
")"
);
}
);
return db;
}
Appointment appointmentFromMap(Map inMap) {
print(
"## appointments AppointmentsDBWorker.appointmentFromMap(): inMap = $inMap");
Appointment appointment = Appointment();
appointment.id = inMap["id"];
appointment.title = inMap["title"];
appointment.description = inMap["description"];
appointment.apptDate = inMap["apptDate"];
appointment.apptTime = inMap["apptTime"];
print(
"## appointments AppointmentsDBWorker.appointmentFromMap(): appointment = $appointment");
return appointment;
}
Map<String, dynamic> appointmentToMap(Appointment inAppointment) {
print(
"## appointments AppointmentsDBWorker.appointmentToMap(): inAppointment = $inAppointment");
Map<String, dynamic> map = Map<String, dynamic>();
map["id"] = inAppointment.id;
map["title"] = inAppointment.title;
map["description"] = inAppointment.description;
map["apptDate"] = inAppointment.apptDate;
map["apptTime"] = inAppointment.apptTime;
print(
"## appointments AppointmentsDBWorker.appointmentToMap(): map = $map");
return map;
}
Future create(Appointment inAppointment) async {
print(
"## appointments AppointmentsDBWorker.create(): inAppointment = $inAppointment");
Database db = await database;
var val = await db.rawQuery("SELECT MAX(id) + 1 AS id FROM appointments");
int id = val.first["id"];
if (id == null) {
id = 1;
}
return await db.rawInsert(
"INSERT INTO appointments (id, title, description, apptDate, apptTime) VALUES (?, ?, ?, ?, ?)",
[
id,
inAppointment.title,
inAppointment.description,
inAppointment.apptDate,
inAppointment.apptTime
]
);
}
Future<Appointment> get(int inID) async {
print("## appointments AppointmentsDBWorker.get(): inID = $inID");
Database db = await database;
var rec = await db.query(
"appointments", where: "id = ?", whereArgs: [ inID]);
print("## appointments AppointmentsDBWorker.get(): rec.first = $rec.first");
return appointmentFromMap(rec.first);
}
Future<List> getAll() async {
Database db = await database;
var recs = await db.query("appointments");
var list = recs.isNotEmpty
? recs.map((m) => appointmentFromMap(m)).toList()
: [];
print("## appointments AppointmentsDBWorker.getAll(): list = $list");
return list;
}
Future update(Appointment inAppointment) async {
print(
"## appointments AppointmentsDBWorker.update(): inAppointment = $inAppointment");
Database db = await database;
return await db.update(
"appointments", appointmentToMap(inAppointment), where: "id = ?",
whereArgs: [ inAppointment.id]
);
}
Future delete(int inID) async {
print("## appointments AppointmentsDBWorker.delete(): inID = $inID");
Database db = await database;
return await db.delete("appointments", where: "id = ?", whereArgs: [ inID]);
}
}
import "dart:async";
import "package:flutter/material.dart";import "package:scoped_model/scoped_model.dart";
import "../utils.dart" as utils;
import "AppointmentsDBWorker.dart";
import "AppointmentsModel.dart" show AppointmentsModel, appointmentsModel;
class AppointmentsEntry extends StatelessWidget {
final TextEditingController _titleEditingController = TextEditingController();
final TextEditingController _descriptionEditingController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
AppointmentsEntry() {
print("## AppointmentsEntry.constructor");
_titleEditingController.addListener(() {
appointmentsModel.entityBeingEdited.title = _titleEditingController.text;
});
_descriptionEditingController.addListener(() {
appointmentsModel.entityBeingEdited.description =
_descriptionEditingController.text;
});
}
Widget build(BuildContext inContext) {
print("## AppointmentsEntry.build()");
if (appointmentsModel.entityBeingEdited != null) {
_titleEditingController.text = appointmentsModel.entityBeingEdited.title;
_descriptionEditingController.text =
appointmentsModel.entityBeingEdited.description;
}
return ScopedModel(
model: appointmentsModel,
child: ScopedModelDescendant<AppointmentsModel>(
builder: (BuildContext inContext, Widget inChild,
AppointmentsModel inModel) {
return Scaffold(
bottomNavigationBar: Padding(
padding: EdgeInsets.symmetric(
vertical: 0, horizontal: 10),
child: Row(
children: [
FlatButton(
child: Text("Cancel"),
onPressed: () {
FocusScope.of(inContext).requestFocus(
FocusNode());
inModel.setStackIndex(0);
}
),
Spacer(),
FlatButton(
child: Text("Save"),
onPressed: () {
_save(inContext, appointmentsModel);
}
)
]
)
),
body: Form(
key: _formKey,
child: ListView(
children: [
ListTile(
leading: Icon(Icons.subject),
title: TextFormField(
decoration: InputDecoration(
hintText: "Title"),
controller: _titleEditingController,
validator: (String inValue) {
if (inValue.length == 0) {
return "Please enter a title";
}
return null;
}
)
),
ListTile(
leading: Icon(Icons.description),
title: TextFormField(
keyboardType: TextInputType.multiline,
maxLines: 4,
decoration: InputDecoration(
hintText: "Description"),
controller: _descriptionEditingController
)
),
ListTile(
leading: Icon(Icons.today),
title: Text("Date"),
subtitle: Text(
appointmentsModel.chosenDate == null
? ""
: appointmentsModel.chosenDate),
trailing: IconButton(
icon: Icon(Icons.edit),
color: Colors.blue,
onPressed: () async {
String chosenDate = await utils
.selectDate(
inContext, appointmentsModel,
appointmentsModel.entityBeingEdited
.apptDate
);
if (chosenDate != null) {
appointmentsModel.entityBeingEdited
.apptDate = chosenDate;
}
}
)
),
ListTile(
leading: Icon(Icons.alarm),
title: Text("Time"),
subtitle: Text(
appointmentsModel.apptTime == null
? ""
: appointmentsModel.apptTime),
trailing: IconButton(
icon: Icon(Icons.edit),
color: Colors.blue,
onPressed: () => _selectTime(inContext)
)
)
]
)
)
);
}
)
);
}
Future _selectTime(BuildContext inContext) async {
TimeOfDay initialTime = TimeOfDay.now();
if (appointmentsModel.entityBeingEdited.apptTime != null) {
List timeParts = appointmentsModel.entityBeingEdited.apptTime.split(",");
initialTime = TimeOfDay(
hour: int.parse(timeParts[0]), minute: int.parse(timeParts[1]));
}
TimeOfDay picked = await showTimePicker(
context: inContext, initialTime: initialTime);
if (picked != null) {
appointmentsModel.entityBeingEdited.apptTime =
"${picked.hour},${picked.minute}";
appointmentsModel.setApptTime(picked.format(inContext));
}
}
void _save(BuildContext inContext, AppointmentsModel inModel) async {
print("## AppointmentsEntry._save()");
if (!_formKey.currentState.validate()) {
return;
}
if (inModel.entityBeingEdited.id == null) {
print("## AppointmentsEntry._save(): Creating: ${inModel
.entityBeingEdited}");
await AppointmentsDBWorker.db.create(appointmentsModel.entityBeingEdited);
} else {
print("## AppointmentsEntry._save(): Updating: ${inModel
.entityBeingEdited}");
await AppointmentsDBWorker.db.update(appointmentsModel.entityBeingEdited);
}
appointmentsModel.loadData("appointments", AppointmentsDBWorker.db);
inModel.setStackIndex(0);
Scaffold.of(inContext).showSnackBar(
SnackBar(
backgroundColor: Colors.green,
duration: Duration(seconds: 2),
content: Text("Appointment saved")
)
);
}
}
import "package:flutter/material.dart";
import 'package:flutter_slidable/flutter_slidable.dart';
import "package:scoped_model/scoped_model.dart";
import "package:intl/intl.dart";
import "package:flutter_calendar_carousel/flutter_calendar_carousel.dart";
import "package:flutter_calendar_carousel/classes/event.dart";
import "package:flutter_calendar_carousel/classes/event_list.dart";
import "AppointmentsDBWorker.dart";
import "AppointmentsModel.dart" show Appointment, AppointmentsModel, appointmentsModel;
class AppointmentsList extends StatelessWidget {
Widget build(BuildContext inContext) {
print("## AppointmentssList.build()");
EventList<Event> _markedDateMap = EventList();
for (int i = 0; i < appointmentsModel.entityList.length; i++) {
Appointment appointment = appointmentsModel.entityList[i];
List dateParts = appointment.apptDate.split(",");
DateTime apptDate = DateTime(
int.parse(dateParts[0]), int.parse(dateParts[1]),
int.parse(dateParts[2]));
_markedDateMap.add(
apptDate, Event(date: apptDate,
icon: Container(decoration: BoxDecoration(color: Colors.blue)))
);
}
return ScopedModel<AppointmentsModel>(
model: appointmentsModel,
child: ScopedModelDescendant<AppointmentsModel>(
builder: (inContext, inChild, inModel) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.white),
onPressed: () async {
appointmentsModel.entityBeingEdited = Appointment();
DateTime now = DateTime.now();
appointmentsModel.entityBeingEdited.apptDate =
"${now.year},${now.month},${now.day}";
appointmentsModel.setChosenDate(
DateFormat.yMMMMd("en_US").format(now.toLocal()));
appointmentsModel.setApptTime(null);
appointmentsModel.setStackIndex(1);
}
),
body: Column(
children: [
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10),
child: CalendarCarousel<Event>(
thisMonthDayBorderColor: Colors.grey,
daysHaveCircularBorder: false,
markedDatesMap: _markedDateMap,
onDayPressed: (DateTime inDate, List<
Event> inEvents) {
_showAppointments(inDate, inContext);
}
)
)
)
]
)
);
}
)
);
}
void _showAppointments(DateTime inDate, BuildContext inContext) async {
print(
"## AppointmentsList._showAppointments(): inDate = $inDate (${inDate
.year},${inDate.month},${inDate.day})"
);
print(
"## AppointmentsList._showAppointments(): appointmentsModel.entityList.length = "
"${appointmentsModel.entityList.length}");
print(
"## AppointmentsList._showAppointments(): appointmentsModel.entityList = "
"${appointmentsModel.entityList}");
showModalBottomSheet(
context: inContext,
builder: (BuildContext inContext) {
return ScopedModel<AppointmentsModel>(
model: appointmentsModel,
child: ScopedModelDescendant<AppointmentsModel>(
builder: (BuildContext inContext, Widget inChild,
AppointmentsModel inModel) {
return Scaffold(
body: Container(
child: Padding(
padding: EdgeInsets.all(10),
child: GestureDetector(
child: Column(
children: [
Text(
DateFormat.yMMMMd("en_US").format(
inDate.toLocal()),
textAlign: TextAlign.center,
style: TextStyle(color: Theme
.of(inContext)
.accentColor, fontSize: 24)
),
Divider(),
Expanded(
child: ListView.builder(
itemCount: appointmentsModel
.entityList.length,
itemBuilder: (
BuildContext inBuildContext,
int inIndex) {
Appointment appointment = appointmentsModel
.entityList[inIndex];
print(
"## AppointmentsList._showAppointments().ListView.builder(): "
"appointment = $appointment");
if (appointment.apptDate !=
"${inDate
.year},${inDate
.month},${inDate
.day}") {
return Container(
height: 0);
}
print(
"## AppointmentsList._showAppointments().ListView.builder(): "
"INCLUDING appointment = $appointment");
String apptTime = "";
if (appointment.apptTime !=
null) {
List timeParts = appointment
.apptTime.split(
",");
TimeOfDay at = TimeOfDay(
hour: int.parse(
timeParts[0]),
minute: int.parse(
timeParts[1])
);
apptTime =
" (${at.format(
inContext)})";
}
return Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: .25,
child: Container(
margin: EdgeInsets
.only(
bottom: 8),
color: Colors.grey
.shade300,
child: ListTile(
title: Text(
"${appointment
.title}$apptTime"),
subtitle: appointment
.description ==
null ?
null : Text(
"${appointment
.description}"),
onTap: () async {
_editAppointment(
inContext,
appointment);
}
)
),
secondaryActions: [
IconSlideAction(
caption: "Delete",
color: Colors.red,
icon: Icons
.delete,
onTap: () =>
_deleteAppointment(
inBuildContext,
appointment)
)
]
);
}
)
)
]
)
)
)
)
);
}
)
);
}
);
}
void _editAppointment(BuildContext inContext,
Appointment inAppointment) async {
print(
"## AppointmentsList._editAppointment(): inAppointment = $inAppointment");
appointmentsModel.entityBeingEdited =
await AppointmentsDBWorker.db.get(inAppointment.id);
if (appointmentsModel.entityBeingEdited.apptDate == null) {
appointmentsModel.setChosenDate(null);
} else {
List dateParts = appointmentsModel.entityBeingEdited.apptDate.split(",");
DateTime apptDate = DateTime(
int.parse(dateParts[0]), int.parse(dateParts[1]),
int.parse(dateParts[2])
);
appointmentsModel.setChosenDate(
DateFormat.yMMMMd("en_US").format(apptDate.toLocal())
);
}
if (appointmentsModel.entityBeingEdited.apptTime == null) {
appointmentsModel.setApptTime(null);
} else {
List timeParts = appointmentsModel.entityBeingEdited.apptTime.split(",");
TimeOfDay apptTime = TimeOfDay(
hour: int.parse(timeParts[0]), minute: int.parse(timeParts[1])
);
appointmentsModel.setApptTime(apptTime.format(inContext));
}
appointmentsModel.setStackIndex(1);
Navigator.pop(inContext);
}
Future _deleteAppointment(BuildContext inContext,
Appointment inAppointment) async {
print(
"## AppointmentsList._deleteAppointment(): inAppointment = $inAppointment");
return showDialog(
context: inContext,
barrierDismissible: false,
builder: (BuildContext inAlertContext) {
return AlertDialog(
title: Text("Delete Appointment"),
content: Text(
"Are you sure you want to delete ${inAppointment.title}?"),
actions: [
FlatButton(child: Text("Cancel"),
onPressed: () {
Navigator.of(inAlertContext).pop();
}
),
FlatButton(child: Text("Delete"),
onPressed: () async {
await AppointmentsDBWorker.db.delete(inAppointment.id);
Navigator.of(inAlertContext).pop();
Scaffold.of(inContext).showSnackBar(
SnackBar(
backgroundColor: Colors.red,
duration: Duration(seconds: 2),
content: Text("Appointment deleted")
)
);
appointmentsModel.loadData(
"appointments", AppointmentsDBWorker.db);
}
)
]
);
}
);
}
}
import "../BaseModel.dart";
class Appointment {
int id;
String title;
String description;
String apptDate;
String apptTime;
String toString() {
return "{ id=$id, title=$title, description=$description, apptDate=$apptDate, apptDate=$apptTime }";
}
}
class AppointmentsModel extends BaseModel {
String apptTime;
void setApptTime(String inApptTime) {
apptTime = inApptTime;
notifyListeners();
}
}
AppointmentsModel appointmentsModel = AppointmentsModel();
import "package:scoped_model/scoped_model.dart";
class BaseModel extends Model {
int stackIndex = 0;
List entityList = [];
var entityBeingEdited;
String chosenDate;
void setChosenDate(String inDate) {
print("## BaseModel.setChosenDate(): inDate = $inDate");
chosenDate = inDate;
notifyListeners();
}
void loadData(String inEntityType, dynamic inDatabase) async {
print("## ${inEntityType}Model.loadData()");
entityList = await inDatabase.getAll();
notifyListeners();
}
void setStackIndex(int inStackIndex) {
print("## BaseModel.setStackIndex(): inStackIndex = $inStackIndex");
stackIndex = inStackIndex;
notifyListeners();
}
}
view raw BaseModel.dart hosted with ❤ by GitHub
import "package:flutter/material.dart";import "package:scoped_model/scoped_model.dart";
import "ContactsDBWorker.dart";
import "ContactsList.dart";
import "ContactsEntry.dart";
import "ContactsModel.dart" show ContactsModel, contactsModel;
class Contacts extends StatelessWidget {
Contacts() {
print("## Contacts.constructor");
contactsModel.loadData("contacts", ContactsDBWorker.db);
}
Widget build(BuildContext inContext) {
print("## Contacts.build()");
return ScopedModel<ContactsModel>(
model: contactsModel,
child: ScopedModelDescendant<ContactsModel>(
builder: (BuildContext inContext, Widget inChild,
ContactsModel inModel) {
return IndexedStack(
index: inModel.stackIndex,
children: [
ContactsList(),
ContactsEntry()
]
);
}
)
);
}
}
view raw Contacts.dart hosted with ❤ by GitHub
import "package:path/path.dart";
import "package:sqflite/sqflite.dart";
import "../utils.dart" as utils;
import "ContactsModel.dart";
class ContactsDBWorker {
ContactsDBWorker._();
static final ContactsDBWorker db = ContactsDBWorker._();
Database _db;
Future get database async {
if (_db == null) {
_db = await init();
}
print("## Contacts ContactsDBWorker.get-database(): _db = $_db");
return _db;
}
Future<Database> init() async {
print("Contacts ContactsDBWorker.init()");
String path = join(utils.docsDir.path, "contacts.db");
print("## contacts ContactsDBWorker.init(): path = $path");
Database db = await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database inDB, int inVersion) async {
await inDB.execute(
"CREATE TABLE IF NOT EXISTS contacts ("
"id INTEGER PRIMARY KEY,"
"name TEXT,"
"email TEXT,"
"phone TEXT,"
"birthday TEXT"
")"
);
}
);
return db;
}
Contact contactFromMap(Map inMap) {
print("## Contacts ContactsDBWorker.contactFromMap(): inMap = $inMap");
Contact contact = Contact();
contact.id = inMap["id"];
contact.name = inMap["name"];
contact.phone = inMap["phone"];
contact.email = inMap["email"];
contact.birthday = inMap["birthday"];
print("## Contacts ContactsDBWorker.contactFromMap(): contact = $contact");
return contact;
}
Map<String, dynamic> contactToMap(Contact inContact) {
print(
"## Contacts ContactsDBWorker.contactToMap(): inContact = $inContact");
Map<String, dynamic> map = Map<String, dynamic>();
map["id"] = inContact.id;
map["name"] = inContact.name;
map["phone"] = inContact.phone;
map["email"] = inContact.email;
map["birthday"] = inContact.birthday;
print("## Contacts ContactsDBWorker.contactToMap(): map = $map");
return map;
}
Future create(Contact inContact) async {
print("## Contacts ContactsDBWorker.create(): inContact = $inContact");
Database db = await database;
var val = await db.rawQuery("SELECT MAX(id) + 1 AS id FROM contacts");
int id = val.first["id"];
if (id == null) {
id = 1;
}
await db.rawInsert(
"INSERT INTO contacts (id, name, email, phone, birthday) VALUES (?, ?, ?, ?, ?)",
[
id,
inContact.name,
inContact.email,
inContact.phone,
inContact.birthday
]
);
return id;
}
Future<Contact> get(int inID) async {
print("## Contacts ContactsDBWorker.get(): inID = $inID");
Database db = await database;
var rec = await db.query("contacts", where: "id = ?", whereArgs: [ inID]);
print("## Contacts ContactsDBWorker.get(): rec.first = $rec.first");
return contactFromMap(rec.first);
}
Future<List> getAll() async {
print("## Contacts ContactsDBWorker.getAll()");
Database db = await database;
var recs = await db.query("contacts");
var list = recs.isNotEmpty ? recs.map((m) => contactFromMap(m)).toList() : [
];
print("## Contacts ContactsDBWorker.getAll(): list = $list");
return list;
}
Future update(Contact inContact) async {
print("## Contacts ContactsDBWorker.update(): inContact = $inContact");
Database db = await database;
return await db.update("contacts", contactToMap(inContact), where: "id = ?",
whereArgs: [ inContact.id]);
}
Future delete(int inID) async {
print("## Contacts ContactsDBWorker.delete(): inID = $inID");
Database db = await database;
return await db.delete("contacts", where: "id = ?", whereArgs: [ inID]);
}
}
import "dart:async";
import "dart:io";
import "package:flutter/material.dart";
import "package:path/path.dart";
import "package:scoped_model/scoped_model.dart";
import "package:image_picker/image_picker.dart";
import "../utils.dart" as utils;
import "ContactsDBWorker.dart";
import "ContactsModel.dart" show ContactsModel, contactsModel;
class ContactsEntry extends StatelessWidget {
final TextEditingController _nameEditingController = TextEditingController();
final TextEditingController _phoneEditingController = TextEditingController();
final TextEditingController _emailEditingController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
ContactsEntry() {
print("## ContactsEntry.constructor");
_nameEditingController.addListener(() {
contactsModel.entityBeingEdited.name = _nameEditingController.text;
});
_phoneEditingController.addListener(() {
contactsModel.entityBeingEdited.phone = _phoneEditingController.text;
});
_emailEditingController.addListener(() {
contactsModel.entityBeingEdited.email = _emailEditingController.text;
});
}
Widget build(BuildContext inContext) {
print("## ContactsEntry.build()");
if (contactsModel.entityBeingEdited != null) {
_nameEditingController.text = contactsModel.entityBeingEdited.name;
_phoneEditingController.text = contactsModel.entityBeingEdited.phone;
_emailEditingController.text = contactsModel.entityBeingEdited.email;
}
return ScopedModel(
model: contactsModel,
child: ScopedModelDescendant<ContactsModel>(
builder: (BuildContext inContext, Widget inChild,
ContactsModel inModel) {
File avatarFile = File(join(utils.docsDir.path, "avatar"));
if (avatarFile.existsSync() == false) {
if (inModel.entityBeingEdited != null &&
inModel.entityBeingEdited.id != null) {
avatarFile = File(join(
utils.docsDir.path,
inModel.entityBeingEdited.id.toString()));
}
}
return Scaffold(
bottomNavigationBar: Padding(
padding: EdgeInsets.symmetric(
vertical: 0, horizontal: 10),
child: Row(
children: [
FlatButton(
child: Text("Cancel"),
onPressed: () {
File avatarFile = File(
join(utils.docsDir.path, "avatar"));
if (avatarFile.existsSync()) {
avatarFile.deleteSync();
}
FocusScope.of(inContext).requestFocus(
FocusNode());
inModel.setStackIndex(0);
}
),
Spacer(),
FlatButton(
child: Text("Save"),
onPressed: () {
_save(inContext, inModel);
}
)
]
)),
body: Form(
key: _formKey,
child: ListView(
children: [
ListTile(
title: avatarFile.existsSync()
? Image.file(avatarFile)
: Text("No avatar image for this contact"),
trailing: IconButton(
icon: Icon(Icons.edit),
color: Colors.blue,
onPressed: () => _selectAvatar(inContext)
)
),
ListTile(
leading: Icon(Icons.person),
title: TextFormField(
decoration: InputDecoration(
hintText: "Name"),
controller: _nameEditingController,
validator: (String inValue) {
if (inValue.length == 0) {
return "Please enter a name";
}
return null;
}
)
),
ListTile(
leading: Icon(Icons.phone),
title: TextFormField(
keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: "Phone"),
controller: _phoneEditingController
)
),
ListTile(
leading: Icon(Icons.email),
title: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: "Email"),
controller: _emailEditingController
)
),
ListTile(
leading: Icon(Icons.today),
title: Text("Birthday"),
subtitle: Text(contactsModel.chosenDate == null
? ""
: contactsModel.chosenDate),
trailing: IconButton(
icon: Icon(Icons.edit),
color: Colors.blue,
onPressed: () async {
String chosenDate = await utils
.selectDate(
inContext, contactsModel,
contactsModel.entityBeingEdited
.birthday
);
if (chosenDate != null) {
contactsModel.entityBeingEdited
.birthday =
chosenDate;
}
}
)
)
]
)
)
);
}
)
);
}
Future _selectAvatar(BuildContext inContext) {
print("ContactsEntry._selectAvatar()");
return showDialog(context: inContext,
builder: (BuildContext inDialogContext) {
return AlertDialog(
content: SingleChildScrollView(
child: ListBody(
children: [
GestureDetector(
child: Text("Take a picture"),
onTap: () async {
var cameraImage = await ImagePicker.pickImage(
source: ImageSource.camera);
if (cameraImage != null) {
cameraImage.copySync(
join(utils.docsDir.path, "avatar"));
contactsModel.triggerRebuild();
}
Navigator.of(inDialogContext).pop();
}
),
Padding(padding: EdgeInsets.all(10)),
GestureDetector(
child: Text("Select From Gallery"),
onTap: () async {
var galleryImage = await ImagePicker.pickImage(
source: ImageSource.gallery);
if (galleryImage != null) {
galleryImage.copySync(
join(utils.docsDir.path, "avatar"));
contactsModel.triggerRebuild();
}
Navigator.of(inDialogContext).pop();
}
)
]
)
)
);
}
);
}
void _save(BuildContext inContext, ContactsModel inModel) async {
print("## ContactsEntry._save()");
if (!_formKey.currentState.validate()) {
return;
}
var id;
if (inModel.entityBeingEdited.id == null) {
print("## ContactsEntry._save(): Creating: ${inModel.entityBeingEdited}");
id = await ContactsDBWorker.db.create(contactsModel.entityBeingEdited);
} else {
print("## ContactsEntry._save(): Updating: ${inModel.entityBeingEdited}");
id = contactsModel.entityBeingEdited.id;
await ContactsDBWorker.db.update(contactsModel.entityBeingEdited);
}
File avatarFile = File(join(utils.docsDir.path, "avatar"));
if (avatarFile.existsSync()) {
print("## ContactsEntry._save(): Renaming avatar file to id = $id");
avatarFile.renameSync(join(utils.docsDir.path, id.toString()));
}
contactsModel.loadData("contacts", ContactsDBWorker.db);
inModel.setStackIndex(0);
Scaffold.of(inContext).showSnackBar(
SnackBar(
backgroundColor: Colors.green,
duration: Duration(seconds: 2),
content: Text("Contact saved")
)
);
}
}
import "dart:io";
import "package:flutter/material.dart";import "package:scoped_model/scoped_model.dart";
import "package:flutter_slidable/flutter_slidable.dart";
import "package:intl/intl.dart";
import "package:path/path.dart";
import "../utils.dart" as utils;
import "ContactsDBWorker.dart";
import "ContactsModel.dart" show Contact, ContactsModel, contactsModel;
class ContactsList extends StatelessWidget {
Widget build(BuildContext inContext) {
print("## ContactsList.build()");
return ScopedModel<ContactsModel>(
model: contactsModel,
child: ScopedModelDescendant<ContactsModel>(
builder: (BuildContext inContext, Widget inChild,
ContactsModel inModel) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.white),
onPressed: () async {
File avatarFile = File(
join(utils.docsDir.path, "avatar"));
if (avatarFile.existsSync()) {
avatarFile.deleteSync();
}
contactsModel.entityBeingEdited = Contact();
contactsModel.setChosenDate(null);
contactsModel.setStackIndex(1);
}
),
body: ListView.builder(
itemCount: contactsModel.entityList.length,
itemBuilder: (BuildContext inBuildContext, int inIndex) {
Contact contact = contactsModel.entityList[inIndex];
File avatarFile = File(
join(utils.docsDir.path, contact.id.toString()));
bool avatarFileExists = avatarFile.existsSync();
print(
"## ContactsList.build(): avatarFile: $avatarFile -- avatarFileExists=$avatarFileExists");
return Column(
children: [
Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: .25,
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.indigoAccent,
foregroundColor: Colors.white,
backgroundImage: avatarFileExists
? FileImage(
avatarFile)
: null,
child: avatarFileExists ? null : Text(
contact.name.substring(0, 1)
.toUpperCase())
),
title: Text("${contact.name}"),
subtitle: contact.phone == null
? null
: Text(
"${contact.phone}"),
onTap: () async {
File avatarFile = File(
join(utils.docsDir.path,
"avatar"));
if (avatarFile.existsSync()) {
avatarFile.deleteSync();
}
contactsModel.entityBeingEdited =
await ContactsDBWorker.db.get(
contact.id);
if (contactsModel.entityBeingEdited
.birthday ==
null) {
contactsModel.setChosenDate(null);
} else {
List dateParts = contactsModel
.entityBeingEdited.birthday.split(
",");
DateTime birthday = DateTime(
int.parse(dateParts[0]),
int.parse(
dateParts[1]),
int.parse(dateParts[2])
);
contactsModel.setChosenDate(
DateFormat.yMMMMd(
"en_US").format(
birthday.toLocal()));
}
contactsModel.setStackIndex(1);
}
),
secondaryActions: [
IconSlideAction(
caption: "Delete",
color: Colors.red,
icon: Icons.delete,
onTap: () =>
_deleteContact(inContext, contact)
)
]
),
Divider()
]
);
}
)
);
}
)
);
}
Future _deleteContact(BuildContext inContext, Contact inContact) async {
print("## ContactsList._deleteContact(): inContact = $inContact");
return showDialog(
context: inContext,
barrierDismissible: false,
builder: (BuildContext inAlertContext) {
return AlertDialog(
title: Text("Delete Contact"),
content: Text(
"Are you sure you want to delete ${inContact.name}?"),
actions: [
FlatButton(child: Text("Cancel"),
onPressed: () {
Navigator.of(inAlertContext).pop();
}
),
FlatButton(child: Text("Delete"),
onPressed: () async {
File avatarFile = File(
join(utils.docsDir.path, inContact.id.toString()));
if (avatarFile.existsSync()) {
avatarFile.deleteSync();
}
await ContactsDBWorker.db.delete(inContact.id);
Navigator.of(inAlertContext).pop();
Scaffold.of(inContext).showSnackBar(
SnackBar(
backgroundColor: Colors.red,
duration: Duration(seconds: 2),
content: Text("Contact deleted")
)
);
contactsModel.loadData("contacts", ContactsDBWorker.db);
}
)
]
);
}
);
}
}
import "../BaseModel.dart";
class Contact {
int id;
String name;
String phone;
String email;
String birthday;
String toString() {
return "{ id=$id, name=$name, phone=$phone, email=$email, birthday=$birthday }";
}
}
class ContactsModel extends BaseModel {
void triggerRebuild() {
print("## ContactsModel.triggerRebuild()");
notifyListeners();
}
}
ContactsModel contactsModel = ContactsModel();
import "dart:io";
import "package:flutter/material.dart";import "package:path_provider/path_provider.dart";
import "appointments/Appointments.dart";
import "contacts/Contacts.dart";
import "notes/Notes.dart";
import "tasks/Tasks.dart";
import "utils.dart" as utils;
void main() {
WidgetsFlutterBinding.ensureInitialized();
print("## main(): FlutterBook Starting");
startMeUp() async {
Directory docsDir = await getApplicationDocumentsDirectory();
utils.docsDir = docsDir;
runApp(FlutterBook());
}
startMeUp();
}
class FlutterBook extends StatelessWidget {
Widget build(BuildContext inContext) {
print("## FlutterBook.build()");
return MaterialApp(
home: DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
title: Text("FlutterBook"),
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.date_range),
text: "Appointments"),
Tab(icon: Icon(Icons.contacts), text: "Contacts"),
Tab(icon: Icon(Icons.note), text: "Notes"),
Tab(icon: Icon(Icons.assignment_turned_in),
text: "Tasks")
]
)
),
body: TabBarView(
children: [
Appointments(),
Contacts(),
Notes(),
Tasks()
]
)
)
)
);
}
}
view raw main.dart hosted with ❤ by GitHub
import "package:flutter/material.dart";
import "package:scoped_model/scoped_model.dart";
import "NotesDBWorker.dart";
import "NotesList.dart";
import "NotesEntry.dart";
import "NotesModel.dart" show NotesModel, notesModel;
class Notes extends StatelessWidget {
Notes() {
print("## Notes.constructor");
notesModel.loadData("notes", NotesDBWorker.db);
}
Widget build(BuildContext inContext) {
print("## Notes.build()");
return ScopedModel<NotesModel>(
model: notesModel,
child: ScopedModelDescendant<NotesModel>(
builder: (BuildContext inContext, Widget inChild,
NotesModel inModel) {
return IndexedStack(
index: inModel.stackIndex,
children: [
NotesList(),
NotesEntry()
]
);
}
)
);
}
}
view raw Notes.dart hosted with ❤ by GitHub
import "package:path/path.dart";
import "package:sqflite/sqflite.dart";
import "../utils.dart" as utils;
import "NotesModel.dart";
class NotesDBWorker {
NotesDBWorker._();
static final NotesDBWorker db = NotesDBWorker._();
Database _db;
Future get database async {
if (_db == null) {
_db = await init();
}
print("## Notes NotesDBWorker.get-database(): _db = $_db");
return _db;
}
Future<Database> init() async {
print("Notes NotesDBWorker.init()");
String path = join(utils.docsDir.path, "notes.db");
print("## notes NotesDBWorker.init(): path = $path");
Database db = await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database inDB, int inVersion) async {
await inDB.execute(
"CREATE TABLE IF NOT EXISTS notes ("
"id INTEGER PRIMARY KEY,"
"title TEXT,"
"content TEXT,"
"color TEXT"
")"
);
}
);
return db;
}
Note noteFromMap(Map inMap) {
print("## Notes NotesDBWorker.noteFromMap(): inMap = $inMap");
Note note = Note();
note.id = inMap["id"];
note.title = inMap["title"];
note.content = inMap["content"];
note.color = inMap["color"];
print("## Notes NotesDBWorker.noteFromMap(): note = $note");
return note;
}
Map<String, dynamic> noteToMap(Note inNote) {
print("## Notes NotesDBWorker.noteToMap(): inNote = $inNote");
Map<String, dynamic> map = Map<String, dynamic>();
map["id"] = inNote.id;
map["title"] = inNote.title;
map["content"] = inNote.content;
map["color"] = inNote.color;
print("## notes NotesDBWorker.noteToMap(): map = $map");
return map;
}
Future create(Note inNote) async {
print("## Notes NotesDBWorker.create(): inNote = $inNote");
Database db = await database;
var val = await db.rawQuery("SELECT MAX(id) + 1 AS id FROM notes");
int id = val.first["id"];
if (id == null) {
id = 1;
}
return await db.rawInsert(
"INSERT INTO notes (id, title, content, color) VALUES (?, ?, ?, ?)",
[
id,
inNote.title,
inNote.content,
inNote.color
]
);
}
Future<Note> get(int inID) async {
print("## Notes NotesDBWorker.get(): inID = $inID");
Database db = await database;
var rec = await db.query("notes", where: "id = ?", whereArgs: [ inID]);
print("## Notes NotesDBWorker.get(): rec.first = $rec.first");
return noteFromMap(rec.first);
}
Future<List> getAll() async {
print("## Notes NotesDBWorker.getAll()");
Database db = await database;
var recs = await db.query("notes");
var list = recs.isNotEmpty ? recs.map((m) => noteFromMap(m)).toList() : [];
print("## Notes NotesDBWorker.getAll(): list = $list");
return list;
}
Future update(Note inNote) async {
print("## Notes NotesDBWorker.update(): inNote = $inNote");
Database db = await database;
return await db.update(
"notes", noteToMap(inNote), where: "id = ?", whereArgs: [ inNote.id]);
}
Future delete(int inID) async {
print("## Notes NotesDBWorker.delete(): inID = $inID");
Database db = await database;
return await db.delete("notes", where: "id = ?", whereArgs: [ inID]);
}
}
import "package:flutter/material.dart";
import "package:scoped_model/scoped_model.dart";
import "NotesDBWorker.dart";
import "NotesModel.dart" show NotesModel, notesModel;
class NotesEntry extends StatelessWidget {
final TextEditingController _titleEditingController = TextEditingController();
final TextEditingController _contentEditingController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
NotesEntry() {
print("## NotesEntry.constructor");
_titleEditingController.addListener(() {
notesModel.entityBeingEdited.title = _titleEditingController.text;
});
_contentEditingController.addListener(() {
notesModel.entityBeingEdited.content = _contentEditingController.text;
});
}
Widget build(BuildContext inContext) {
print("## NotesEntry.build()");
if (notesModel.entityBeingEdited != null) {
_titleEditingController.text = notesModel.entityBeingEdited.title;
_contentEditingController.text = notesModel.entityBeingEdited.content;
}
return ScopedModel(
model: notesModel,
child: ScopedModelDescendant<NotesModel>(
builder: (BuildContext inContext, Widget inChild,
NotesModel inModel) {
return Scaffold(
bottomNavigationBar: Padding(
padding: EdgeInsets.symmetric(
vertical: 0, horizontal: 10),
child: Row(
children: [
FlatButton(
child: Text("Cancel"),
onPressed: () {
FocusScope.of(inContext).requestFocus(
FocusNode());
inModel.setStackIndex(0);
}
),
Spacer(),
FlatButton(
child: Text("Save"),
onPressed: () {
_save(inContext, notesModel);
}
)
]
)
),
body: Form(
key: _formKey,
child: ListView(
children: [
ListTile(
leading: Icon(Icons.title),
title: TextFormField(
decoration: InputDecoration(
hintText: "Title"),
controller: _titleEditingController,
validator: (String inValue) {
if (inValue.length == 0) {
return "Please enter a title";
}
return null;
}
)
),
ListTile(
leading: Icon(Icons.content_paste),
title: TextFormField(
keyboardType: TextInputType.multiline,
maxLines: 8,
decoration: InputDecoration(
hintText: "Content"),
controller: _contentEditingController,
validator: (String inValue) {
if (inValue.length == 0) {
return "Please enter content";
}
return null;
}
)
),
ListTile(
leading: Icon(Icons.color_lens),
title: Row(
children: [
GestureDetector(
child: Container(
decoration: ShapeDecoration(shape:
Border.all(color: Colors.red,
width: 18) +
Border.all(
width: 6,
color: notesModel.color ==
"red"
? Colors.red
: Theme
.of(inContext)
.canvasColor
)
)
),
onTap: () {
notesModel.entityBeingEdited.color =
"red";
notesModel.setColor("red");
}
),
Spacer(),
GestureDetector(
child: Container(
decoration: ShapeDecoration(shape:
Border.all(color: Colors.green,
width: 18) +
Border.all(
width: 6,
color: notesModel.color ==
"green"
? Colors.green
: Theme
.of(inContext)
.canvasColor
)
)
),
onTap: () {
notesModel.entityBeingEdited.color =
"green";
notesModel.setColor("green");
}
),
Spacer(),
GestureDetector(
child: Container(
decoration: ShapeDecoration(shape:
Border.all(color: Colors.blue,
width: 18) +
Border.all(
width: 6,
color: notesModel.color ==
"blue"
? Colors.blue
: Theme
.of(inContext)
.canvasColor
)
)
),
onTap: () {
notesModel.entityBeingEdited.color =
"blue";
notesModel.setColor("blue");
}
),
Spacer(),
GestureDetector(
child: Container(
decoration: ShapeDecoration(shape:
Border.all(color: Colors.yellow,
width: 18) +
Border.all(
width: 6,
color: notesModel.color ==
"yellow"
? Colors.yellow
: Theme
.of(inContext)
.canvasColor
)
)
),
onTap: () {
notesModel.entityBeingEdited.color =
"yellow";
notesModel.setColor("yellow");
}
),
Spacer(),
GestureDetector(
child: Container(
decoration: ShapeDecoration(shape:
Border.all(color: Colors.grey,
width: 18) +
Border.all(
width: 6,
color: notesModel.color ==
"grey"
? Colors.grey
: Theme
.of(inContext)
.canvasColor
)
)
),
onTap: () {
notesModel.entityBeingEdited.color =
"grey";
notesModel.setColor("grey");
}
),
Spacer(),
GestureDetector(
child: Container(
decoration: ShapeDecoration(shape:
Border.all(color: Colors.purple,
width: 18) +
Border.all(
width: 6,
color: notesModel.color ==
"purple"
? Colors.purple
: Theme
.of(inContext)
.canvasColor
)
)
),
onTap: () {
notesModel.entityBeingEdited.color =
"purple";
notesModel.setColor("purple");
}
)
]
)
)
]
)
)
);
}
)
);
}
void _save(BuildContext inContext, NotesModel inModel) async {
print("## NotesEntry._save()");
if (!_formKey.currentState.validate()) {
return;
}
if (inModel.entityBeingEdited.id == null) {
print("## NotesEntry._save(): Creating: ${inModel.entityBeingEdited}");
await NotesDBWorker.db.create(notesModel.entityBeingEdited);
} else {
print("## NotesEntry._save(): Updating: ${inModel.entityBeingEdited}");
await NotesDBWorker.db.update(notesModel.entityBeingEdited);
}
notesModel.loadData("notes", NotesDBWorker.db);
inModel.setStackIndex(0);
Scaffold.of(inContext).showSnackBar(
SnackBar(
backgroundColor: Colors.green,
duration: Duration(seconds: 2),
content: Text("Note saved")
)
);
}
}
view raw NotesEntry.dart hosted with ❤ by GitHub
import "package:flutter/material.dart";
import "package:scoped_model/scoped_model.dart";
import "package:flutter_slidable/flutter_slidable.dart";
import "NotesDBWorker.dart";
import "NotesModel.dart" show Note, NotesModel, notesModel;
class NotesList extends StatelessWidget {
Widget build(BuildContext inContext) {
print("## NotesList.build()");
return ScopedModel<NotesModel>(
model: notesModel,
child: ScopedModelDescendant<NotesModel>(
builder: (BuildContext inContext, Widget inChild,
NotesModel inModel) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.white),
onPressed: () async {
notesModel.entityBeingEdited = Note();
notesModel.setColor(null);
notesModel.setStackIndex(1);
}
),
body: ListView.builder(
itemCount: notesModel.entityList.length,
itemBuilder: (BuildContext inBuildContext, int inIndex) {
Note note = notesModel.entityList[inIndex];
Color color = Colors.white;
switch (note.color) {
case "red" :
color = Colors.red;
break;
case "green" :
color = Colors.green;
break;
case "blue" :
color = Colors.blue;
break;
case "yellow" :
color = Colors.yellow;
break;
case "grey" :
color = Colors.grey;
break;
case "purple" :
color = Colors.purple;
break;
}
return Container(
padding: EdgeInsets.fromLTRB(20, 20, 20, 0),
child: Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: .25,
secondaryActions: [
IconSlideAction(
caption: "Delete",
color: Colors.red,
icon: Icons.delete,
onTap: () => _deleteNote(inContext, note)
)
],
child: Card(
elevation: 8,
color: color,
child: ListTile(
title: Text("${note.title}"),
subtitle: Text("${note.content}"),
onTap: () async {
notesModel.entityBeingEdited =
await NotesDBWorker.db.get(note.id);
notesModel.setColor(
notesModel.entityBeingEdited
.color);
notesModel.setStackIndex(1);
}
)
)
)
);
}
)
);
}
)
);
}
Future _deleteNote(BuildContext inContext, Note inNote) async {
print("## NotestList._deleteNote(): inNote = $inNote");
return showDialog(
context: inContext,
barrierDismissible: false,
builder: (BuildContext inAlertContext) {
return AlertDialog(
title: Text("Delete Note"),
content: Text("Are you sure you want to delete ${inNote.title}?"),
actions: [
FlatButton(child: Text("Cancel"),
onPressed: () {
Navigator.of(inAlertContext).pop();
}
),
FlatButton(child: Text("Delete"),
onPressed: () async {
await NotesDBWorker.db.delete(inNote.id);
Navigator.of(inAlertContext).pop();
Scaffold.of(inContext).showSnackBar(
SnackBar(
backgroundColor: Colors.red,
duration: Duration(seconds: 2),
content: Text("Note deleted")
)
);
notesModel.loadData("notes", NotesDBWorker.db);
}
)
]
);
}
);
}
}
view raw NotesList.dart hosted with ❤ by GitHub
import "../BaseModel.dart";
class Note {
int id;
String title;
String content;
String color;
String toString() {
return "{ id=$id, title=$title, content=$content, color=$color }";
}
}
class NotesModel extends BaseModel {
String color;
void setColor(String inColor) {
print("## NotesModel.setColor(): inColor = $inColor");
color = inColor;
notifyListeners();
}
}
NotesModel notesModel = NotesModel();
view raw NotesModel.dart hosted with ❤ by GitHub
import "package:flutter/material.dart";import "package:scoped_model/scoped_model.dart";
import "TasksDBWorker.dart";
import "TasksList.dart";
import "TasksEntry.dart";
import "TasksModel.dart" show TasksModel, tasksModel;
class Tasks extends StatelessWidget {
Tasks() {
print("## Tasks.constructor");
tasksModel.loadData("tasks", TasksDBWorker.db);
}
Widget build(BuildContext inContext) {
print("## Tasks.build()");
return ScopedModel<TasksModel>(
model: tasksModel,
child: ScopedModelDescendant<TasksModel>(
builder: (BuildContext inContext, Widget inChild,
TasksModel inModel) {
return IndexedStack(
index: inModel.stackIndex,
children: [
TasksList(),
TasksEntry()
]
);
}
)
);
}
}
view raw Tasks.dart hosted with ❤ by GitHub
import "package:path/path.dart";
import "package:sqflite/sqflite.dart";
import "../utils.dart" as utils;
import "TasksModel.dart";
class TasksDBWorker {
TasksDBWorker._();
static final TasksDBWorker db = TasksDBWorker._();
Database _db;
Future get database async {
if (_db == null) {
_db = await init();
}
print("## tasks TasksDBWorker.get-database(): _db = $_db");
return _db;
}
Future<Database> init() async {
print("## Tasks TasksDBWorker.init()");
String path = join(utils.docsDir.path, "tasks.db");
print("## tasks TasksDBWorker.init(): path = $path");
Database db = await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database inDB, int inVersion) async {
await inDB.execute(
"CREATE TABLE IF NOT EXISTS tasks ("
"id INTEGER PRIMARY KEY,"
"description TEXT,"
"dueDate TEXT,"
"completed TEXT"
")"
);
}
);
return db;
}
Task taskFromMap(Map inMap) {
print("## Tasks TasksDBWorker.taskFromMap(): inMap = $inMap");
Task task = Task();
task.id = inMap["id"];
task.description = inMap["description"];
task.dueDate = inMap["dueDate"];
task.completed = inMap["completed"];
print("## Tasks TasksDBWorker.taskFromMap(): task = $task");
return task;
}
Map<String, dynamic> taskToMap(Task inTask) {
print("## tasks TasksDBWorker.taskToMap(): inTask = $inTask");
Map<String, dynamic> map = Map<String, dynamic>();
map["id"] = inTask.id;
map["description"] = inTask.description;
map["dueDate"] = inTask.dueDate;
map["completed"] = inTask.completed;
print("## tasks TasksDBWorker.taskToMap(): map = $map");
return map;
}
Future create(Task inTask) async {
print("## Tasks TasksDBWorker.create(): inTask = $inTask");
Database db = await database;
var val = await db.rawQuery("SELECT MAX(id) + 1 AS id FROM tasks");
int id = val.first["id"];
if (id == null) {
id = 1;
}
return await db.rawInsert(
"INSERT INTO tasks (id, description, dueDate, completed) VALUES (?, ?, ?, ?)",
[
id,
inTask.description,
inTask.dueDate,
inTask.completed
]
);
}
Future<Task> get(int inID) async {
print("## Tasks TasksDBWorker.get(): inID = $inID");
Database db = await database;
var rec = await db.query("tasks", where: "id = ?", whereArgs: [ inID]);
print("## Tasks TasksDBWorker.get(): rec.first = $rec.first");
return taskFromMap(rec.first);
}
Future<List> getAll() async {
print("## Tasks TasksDBWorker.getAll()");
Database db = await database;
var recs = await db.query("tasks");
var list = recs.isNotEmpty ? recs.map((m) => taskFromMap(m)).toList() : [];
print("## Tasks TasksDBWorker.getAll(): list = $list");
return list;
}
Future update(Task inTask) async {
print("## Tasks TasksDBWorker.update(): inTask = $inTask");
Database db = await database;
return await db.update(
"tasks", taskToMap(inTask), where: "id = ?", whereArgs: [ inTask.id]);
}
Future delete(int inID) async {
print("## Taasks TasksDBWorker.delete(): inID = $inID");
Database db = await database;
return await db.delete("Tasks", where: "id = ?", whereArgs: [ inID]);
}
}
import "package:flutter/material.dart";
import "package:scoped_model/scoped_model.dart";
import "../utils.dart" as utils;
import "TasksDBWorker.dart";
import "TasksModel.dart" show TasksModel, tasksModel;
class TasksEntry extends StatelessWidget {
final TextEditingController _descriptionEditingController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
TasksEntry() {
print("## TasksList.constructor");
_descriptionEditingController.addListener(() {
tasksModel.entityBeingEdited.description =
_descriptionEditingController.text;
});
}
Widget build(BuildContext inContext) {
print("## TasksEntry.build()");
if (tasksModel.entityBeingEdited != null) {
_descriptionEditingController.text =
tasksModel.entityBeingEdited.description;
}
return ScopedModel(
model: tasksModel,
child: ScopedModelDescendant<TasksModel>(
builder: (BuildContext inContext, Widget inChild,
TasksModel inModel) {
return Scaffold(
bottomNavigationBar: Padding(
padding: EdgeInsets.symmetric(
vertical: 0, horizontal: 10),
child: Row(
children: [
FlatButton(child: Text("Cancel"),
onPressed: () {
FocusScope.of(inContext).requestFocus(
FocusNode());
inModel.setStackIndex(0);
}
),
Spacer(),
FlatButton(child: Text("Save"),
onPressed: () {
_save(inContext, tasksModel);
}
)
]
)
),
body: Form(
key: _formKey,
child: ListView(
children: [
ListTile(
leading: Icon(Icons.description),
title: TextFormField(
keyboardType: TextInputType.multiline,
maxLines: 4,
decoration: InputDecoration(
hintText: "Description"),
controller: _descriptionEditingController,
validator: (String inValue) {
if (inValue.length == 0) {
return "Please enter a description";
}
return null;
}
)
),
ListTile(
leading: Icon(Icons.today),
title: Text("Due Date"),
subtitle: Text(
tasksModel.chosenDate == null
? ""
: tasksModel
.chosenDate),
trailing: IconButton(
icon: Icon(Icons.edit), color: Colors.blue,
onPressed: () async {
String chosenDate = await utils
.selectDate(
inContext, tasksModel,
tasksModel.entityBeingEdited.dueDate
);
if (chosenDate != null) {
tasksModel.entityBeingEdited.dueDate =
chosenDate;
}
}
)
)
]
)
)
);
}
)
);
}
void _save(BuildContext inContext, TasksModel inModel) async {
print("## TasksEntry._save()");
if (!_formKey.currentState.validate()) {
return;
}
if (inModel.entityBeingEdited.id == null) {
print("## TasksEntry._save(): Creating: ${inModel.entityBeingEdited}");
await TasksDBWorker.db.create(tasksModel.entityBeingEdited);
} else {
print("## TasksEntry._save(): Updating: ${inModel.entityBeingEdited}");
await TasksDBWorker.db.update(tasksModel.entityBeingEdited);
}
tasksModel.loadData("tasks", TasksDBWorker.db);
inModel.setStackIndex(0);
Scaffold.of(inContext).showSnackBar(
SnackBar(
backgroundColor: Colors.green,
duration: Duration(seconds: 2),
content: Text("Task saved")
)
);
}
}
view raw TasksEntry.dart hosted with ❤ by GitHub
import "package:flutter/material.dart";import "package:scoped_model/scoped_model.dart";
import "package:flutter_slidable/flutter_slidable.dart";
import "package:intl/intl.dart";
import "TasksDBWorker.dart";
import "TasksModel.dart" show Task, TasksModel, tasksModel;
class TasksList extends StatelessWidget {
Widget build(BuildContext inContext) {
print("## TasksList.build()");
return ScopedModel<TasksModel>(
model: tasksModel,
child: ScopedModelDescendant<TasksModel>(
builder: (BuildContext inContext, Widget inChild,
TasksModel inModel) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.white),
onPressed: () async {
tasksModel.entityBeingEdited = Task();
tasksModel.setChosenDate(null);
tasksModel.setStackIndex(1);
}
),
body: ListView.builder(
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
itemCount: tasksModel.entityList.length,
itemBuilder: (BuildContext inBuildContext, int inIndex) {
Task task = tasksModel.entityList[inIndex];
String sDueDate;
if (task.dueDate != null) {
List dateParts = task.dueDate.split(",");
DateTime dueDate = DateTime(
int.parse(dateParts[0]), int.parse(dateParts[1]),
int.parse(dateParts[2])
);
sDueDate =
DateFormat.yMMMMd("en_US").format(
dueDate.toLocal());
}
return Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: .25,
child: ListTile(
leading: Checkbox(
value: task.completed == "true"
? true
: false,
onChanged: (inValue) async {
task.completed = inValue.toString();
await TasksDBWorker.db.update(task);
tasksModel.loadData(
"tasks", TasksDBWorker.db);
}
),
title: Text(
"${task.description}",
style: task.completed == "true"
?
TextStyle(color: Theme
.of(inContext)
.disabledColor,
decoration: TextDecoration.lineThrough)
:
TextStyle(color: Theme
.of(inContext)
.textTheme
.title
.color)
),
subtitle: task.dueDate == null ?
null :
Text(
sDueDate,
style: task.completed == "true" ?
TextStyle(color: Theme
.of(inContext)
.disabledColor,
decoration: TextDecoration.lineThrough)
:
TextStyle(color: Theme
.of(inContext)
.textTheme
.title
.color)
),
onTap: () async {
if (task.completed == "true") {
return;
}
tasksModel.entityBeingEdited =
await TasksDBWorker.db.get(task.id);
if (tasksModel.entityBeingEdited.dueDate ==
null) {
tasksModel.setChosenDate(null);
} else {
tasksModel.setChosenDate(sDueDate);
}
tasksModel.setStackIndex(1);
}
),
secondaryActions: [
IconSlideAction(
caption: "Delete",
color: Colors.red,
icon: Icons.delete,
onTap: () => _deleteTask(inContext, task)
)
]
);
}
)
);
}
)
);
}
Future _deleteTask(BuildContext inContext, Task inTask) async {
print("## TasksList._deleteTask(): inTask = $inTask");
return showDialog(
context: inContext,
barrierDismissible: false,
builder: (BuildContext inAlertContext) {
return AlertDialog(
title: Text("Delete Task"),
content: Text(
"Are you sure you want to delete ${inTask.description}?"),
actions: [
FlatButton(child: Text("Cancel"),
onPressed: () {
Navigator.of(inAlertContext).pop();
}
),
FlatButton(child: Text("Delete"),
onPressed: () async {
await TasksDBWorker.db.delete(inTask.id);
Navigator.of(inAlertContext).pop();
Scaffold.of(inContext).showSnackBar(
SnackBar(
backgroundColor: Colors.red,
duration: Duration(seconds: 2),
content: Text("Task deleted")
)
);
tasksModel.loadData("tasks", TasksDBWorker.db);
}
)
]
);
}
);
}
}
view raw TasksList.dart hosted with ❤ by GitHub
import "../BaseModel.dart";
class Task {
int id;
String description;
String dueDate;
String completed = "false";
String toString() {
return "{ id=$id, description=$description, dueDate=$dueDate, completed=$completed }";
}
}
class TasksModel extends BaseModel {
}
TasksModel tasksModel = TasksModel();
view raw TasksModel.dart hosted with ❤ by GitHub
import "dart:io";import "package:flutter/material.dart";
import "package:intl/intl.dart";
import "BaseModel.dart";
Directory docsDir;
Future selectDate(BuildContext inContext, BaseModel inModel, String inDateString) async {
print("## globals.selectDate()");
DateTime initialDate = DateTime.now();
if (inDateString != null) {
List dateParts = inDateString.split(",");
initialDate = DateTime(int.parse(dateParts[0]), int.parse(dateParts[1]),
int.parse(dateParts[2]));
}
DateTime picked = await showDatePicker(
context: inContext,
initialDate: initialDate,
firstDate: DateTime(1900),
lastDate: DateTime(2100)
);
if (picked != null) {
inModel.setChosenDate(DateFormat.yMMMMd("en_US").format(picked.toLocal()));
return "${picked.year},${picked.month},${picked.day}";
}
}
view raw utils.dart hosted with ❤ by GitHub

No comments:

Post a Comment