Browse Source

Release version ready!

master
kaqu 6 months ago
parent
commit
3c044bee5b
  1. BIN
      assets/images/arrow_left.odg
  2. BIN
      assets/images/arrow_left.png
  3. BIN
      assets/images/arrow_right.odg
  4. BIN
      assets/images/arrow_right.png
  5. BIN
      assets/images/stop.odg
  6. BIN
      assets/images/stop.png
  7. 377
      lib/color_picker.dart
  8. 200
      lib/main.dart
  9. 5
      pubspec.yaml

BIN
assets/images/arrow_left.odg

Binary file not shown.

BIN
assets/images/arrow_left.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
assets/images/arrow_right.odg

Binary file not shown.

BIN
assets/images/arrow_right.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
assets/images/stop.odg

Binary file not shown.

BIN
assets/images/stop.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

377
lib/color_picker.dart

@ -1,377 +0,0 @@
import 'dart:math';
import 'package:flutter/material.dart';
enum PickMode {
Color,
Grey,
}
/// A listener which receives an color in int representation. as used
/// by [BarColorPicker.colorListener] and [CircleColorPicker.colorListener].
typedef ColorListener = void Function(int value);
/// Constant color of thumb shadow
const _kThumbShadowColor = Color(0x44000000);
/// A padding used to calculate bar height(thumbRadius * 2 - kBarPadding).
const _kBarPadding = 4;
/// Base64 encoded image for alpha picker background
//const _kAlphaTexture = "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==";
/// A bar color picker
class BarColorPicker extends StatefulWidget {
/// mode enum of pick a normal color or pick a grey color
final PickMode pickMode;
/// width of bar, if this widget is horizontal, than
/// bar width is this value, if this widget is vertical
/// bar height is this value
final double width;
/// A listener receives color pick events.
final ColorListener colorListener;
/// corner radius of the picker bar, for each corners
final double cornerRadius;
/// specifies the bar orientation
final bool horizontal;
/// thumb fill color
final Color thumbColor;
/// radius of thumb
final double thumbRadius;
/// initial color of this color picker.
final Color initialColor;
BarColorPicker({
Key key,
this.pickMode = PickMode.Color,
this.horizontal = true,
this.width = 200,
this.cornerRadius = 0.0,
this.thumbRadius = 8,
this.initialColor = const Color(0xffff0000),
this.thumbColor = Colors.black,
@required this.colorListener,
})
: assert(pickMode != null),
assert(horizontal != null),
assert(width != null),
assert(cornerRadius != null),
assert(colorListener != null),
assert(initialColor != null),
super(key: key);
@override
_BarColorPickerState createState() => _BarColorPickerState();
}
class _BarColorPickerState extends State<BarColorPicker> {
double percent = 0.0;
List<Color> colors;
double barWidth, barHeight;
@override
void initState() {
super.initState();
if (widget.horizontal) {
barWidth = widget.width;
barHeight = widget.thumbRadius * 2 - _kBarPadding;
} else {
barWidth = widget.thumbRadius * 2 - _kBarPadding;
barHeight = widget.width;
}
switch (widget.pickMode) {
case PickMode.Color:
colors = const [
Color(0xffff0000),
Color(0xffffff00),
Color(0xff00ff00),
Color(0xff00ffff),
Color(0xff0000ff),
Color(0xffff00ff),
Color(0xffff0000)
];
break;
case PickMode.Grey:
colors = const [
Color(0xff000000),
Color(0xffffffff)
];
break;
}
percent = HSVColor
.fromColor(widget.initialColor)
.hue / 360;
}
@override
Widget build(BuildContext context) {
final double thumbRadius = widget.thumbRadius;
final bool horizontal = widget.horizontal;
double thumbLeft, thumbTop;
if (horizontal) {
thumbLeft = barWidth * percent;
} else {
thumbTop = barHeight * percent;
}
// build thumb
Widget thumb = Positioned(
left: thumbLeft,
top: thumbTop,
child: Container(
width: thumbRadius * 2,
height: thumbRadius * 2,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: _kThumbShadowColor,
spreadRadius: 2,
blurRadius: 3,
)
],
color: widget.thumbColor,
borderRadius: BorderRadius.all(Radius.circular(thumbRadius))
),
)
);
// build frame
double frameWidth, frameHeight;
if (horizontal) {
frameWidth = barWidth + thumbRadius * 2;
frameHeight = thumbRadius * 2;
} else {
frameWidth = thumbRadius * 2;
frameHeight = barHeight + thumbRadius * 2;
}
Widget frame = SizedBox(width: frameWidth, height: frameHeight);
// build content
Gradient gradient;
double left, top;
if (horizontal) {
gradient = LinearGradient(colors: colors);
left = thumbRadius;
top = (thumbRadius * 2 - barHeight) / 2;
} else {
gradient = LinearGradient(
colors: colors,
begin: Alignment.topCenter,
end: Alignment.bottomCenter
);
left = (thumbRadius * 2 - barWidth) / 2;
top = thumbRadius;
}
Widget content = Positioned(
left: left,
top: top,
child: Container(
width: barWidth,
height: barHeight,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(widget.cornerRadius)),
gradient: gradient
),
),
);
return GestureDetector(
onPanDown: (details) => handleTouch(details.globalPosition, context),
//onPanStart: (details) => handleTouch(details.globalPosition, context),
onPanUpdate: (details) => handleTouch(details.globalPosition, context),
child: Stack(children: [frame, content, thumb]),
);
}
/// calculate colors picked from palette and update our states.
void handleTouch(Offset globalPosition, BuildContext context) {
RenderBox box = context.findRenderObject();
Offset localPosition = box.globalToLocal(globalPosition);
double percent;
if (widget.horizontal) {
percent = (localPosition.dx - widget.thumbRadius) / barWidth;
} else {
percent = (localPosition.dy - widget.thumbRadius) / barHeight;
}
percent = min(max(0.0, percent), 1.0);
setState(() {
this.percent = percent;
});
switch (widget.pickMode) {
case PickMode.Color:
Color color = HSVColor.fromAHSV(1.0, percent * 360, 1.0, 1.0).toColor();
widget.colorListener(color.value);
break;
case PickMode.Grey:
final int channel = (0xff * percent).toInt();
widget.colorListener(Color
.fromARGB(0xff, channel, channel, channel)
.value);
break;
}
}
}
/// A circle palette color picker.
class CircleColorPicker extends StatefulWidget {
// radius of the color palette, note that radius * 2 is not the final
// width of this widget, instead is (radius + thumbRadius) * 2.
final double radius;
/// thumb fill color.
final Color thumbColor;
/// radius of thumb.
final double thumbRadius;
/// A listener receives color pick events.
final ColorListener colorListener;
/// initial color of this color picker.
final Color initialColor;
CircleColorPicker({
Key key,
this.radius = 120,
this.initialColor = const Color(0xffff0000),
this.thumbColor = Colors.black,
this.thumbRadius = 8,
@required this.colorListener
})
: assert (radius != null),
assert(thumbColor != null),
assert(colorListener != null),
super(key: key);
@override
State<CircleColorPicker> createState() {
return _CircleColorPickerState();
}
}
class _CircleColorPickerState extends State<CircleColorPicker> {
static const List<Color> colors = [
Color(0xffff0000),
Color(0xffffff00),
Color(0xff00ff00),
Color(0xff00ffff),
Color(0xff0000ff),
Color(0xffff00ff),
Color(0xffff0000)
];
double thumbDistanceToCenter;
double thumbRadians;
@override
void initState() {
super.initState();
thumbDistanceToCenter = widget.radius;
final double hue = HSVColor
.fromColor(widget.initialColor)
.hue;
thumbRadians = degreesToRadians(270 - hue);
}
@override
Widget build(BuildContext context) {
final double radius = widget.radius;
final double thumbRadius = widget.thumbRadius;
// compute thumb center coordinate
final double thumbCenterX = radius +
thumbDistanceToCenter * sin(thumbRadians);
final double thumbCenterY = radius +
thumbDistanceToCenter * cos(thumbRadians);
// build thumb widget
Widget thumb = Positioned(
left: thumbCenterX,
top: thumbCenterY,
child: Container(
width: thumbRadius * 2,
height: thumbRadius * 2,
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
BoxShadow(
color: _kThumbShadowColor,
spreadRadius: 2,
blurRadius: 3,
)
],
color: widget.thumbColor,
borderRadius: BorderRadius.all(Radius.circular(thumbRadius))
),
)
);
return GestureDetector(
behavior: HitTestBehavior.opaque,
onPanDown: (details) => handleTouch(details.globalPosition, context),
//onPanStart: (details) => handleTouch(details.globalPosition, context),
onPanUpdate: (details) => handleTouch(details.globalPosition, context),
child: Stack(
children: <Widget>[
SizedBox(
width: (radius + thumbRadius) * 2,
height: (radius + thumbRadius) * 2
),
Positioned(
left: thumbRadius,
top: thumbRadius,
child: Container(
width: radius * 2,
height: radius * 2,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(radius)),
gradient: SweepGradient(colors: colors)
),
),
),
thumb
],
)
);
}
/// calculate colors picked from palette and update our states.
void handleTouch(Offset globalPosition, BuildContext context) {
RenderBox box = context.findRenderObject();
Offset localPosition = box.globalToLocal(globalPosition);
final double centerX = box.size.width / 2;
final double centerY = box.size.height / 2;
final double deltaX = localPosition.dx - centerX;
final double deltaY = localPosition.dy - centerY;
final double distanceToCenter = sqrt(deltaX * deltaX + deltaY * deltaY);
double theta = atan2(deltaX, deltaY);
double degree = 270 - radiansToDegrees(theta);
if (degree < 0) degree = 360 + degree;
widget.colorListener(HSVColor
.fromAHSV(1, degree, 1, 1)
.toColor()
.value);
setState(() {
thumbDistanceToCenter = min(distanceToCenter, widget.radius);
thumbRadians = theta;
});
}
/// convert an angle value from radian to degree representation.
double radiansToDegrees(double radians) {
return (radians + pi) / pi * 180;
}
/// convert an angle value from degree to radian representation.
double degreesToRadians(double degrees) {
return degrees / 180 * pi - pi;
}
}

200
lib/main.dart

@ -3,12 +3,11 @@
//
// History:
// --------
// 24.06.19/KQ Initial version
// 20.07.21/KQ Initial version
//
import 'dart:io';
import 'package:flutter/material.dart';
//import 'color_picker.dart';
int rcMC = 0;
RawDatagramSocket sG;
@ -16,24 +15,22 @@ InternetAddress multicastAddress; //= new InternetAddress('238.255.255.250');
int multicastPort = 1337;
int iCodeValue = 1; // Line 1 (top, 2 = bottom)
void main() => runApp(ColorPickerApp());
void main() => runApp(BicycLEDApp());
class ColorPickerApp extends StatefulWidget {
class BicycLEDApp extends StatefulWidget {
@override
_ColorPickerAppState createState() => _ColorPickerAppState();
_BicycLEDAppState createState() => _BicycLEDAppState();
}
class _ColorPickerAppState extends State<ColorPickerApp> {
class _BicycLEDAppState extends State<BicycLEDApp> {
Color currentColor = Color(0xffff5F00);
int _counter = 0;
final myController = TextEditingController();
String sMsg;
double dalpha = 4.0;
int alpha = 4, red = 255, green = 95, blue = 0;
@override
void dispose() {
// Clean up the controller when the widget is disposed.
myController.dispose();
super.dispose();
}
@ -46,7 +43,7 @@ class _ColorPickerAppState extends State<ColorPickerApp> {
void _incrementCounter() {
setState(() {
String sEntry = myController.text;
String sEntry = sMsg;
if (sEntry.length > 0) {
hex2rgb(currentColor.value);
_counter = _counter + rcMC;
@ -75,26 +72,21 @@ class _ColorPickerAppState extends State<ColorPickerApp> {
});
}
/*
void _onTextChanged(String t) {
print("onTextChanged: $t");
}
*/
void _onLeftIndicatorPressed() {
print("onLeftIndicatorPressed()");
myController.text = "L";
sMsg = "L";
_incrementCounter();
}
void _onRightIndicatorPressed() {
print("onRightIndicatorPressed()");
myController.text = "R";
sMsg = "R";
_incrementCounter();
}
void _onStopIndicatorPressed() {
print("onStopIndicatorPressed()");
myController.text = "S";
sMsg = "S";
_incrementCounter();
}
@ -114,11 +106,8 @@ class _ColorPickerAppState extends State<ColorPickerApp> {
}
rcMC = 1;
sG = s;
int nBytes = s.send("000:000:064:000:255:000".codeUnits,
multicastAddress, multicastPort);
print("Sent: $nBytes bytes, display reset to green.");
});
myController.text = "Send_me!";
sMsg = "S";
}
return MaterialApp(
title: "BicycLED Control",
@ -130,128 +119,75 @@ class _ColorPickerAppState extends State<ColorPickerApp> {
title: Text("BicycLED Control"),
),
body: Align(
alignment: Alignment.topCenter,
alignment: Alignment.center, //topCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(height: 20),
/*Text('Enter text to send: ', textScaleFactor: 2),
TextField(
controller: myController,
onChanged: (text) {
_onTextChanged(text);
},
style: new TextStyle(
fontSize: 40.0,
height: 1.5,
color: currentColor,
),
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'enter here!',
contentPadding:
const EdgeInsets.symmetric(horizontal: 50.0)),
),
*/
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(width: 80),
TextButton(
onPressed: _onLeftIndicatorPressed,
autofocus: false,
clipBehavior: Clip.none,
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.deepOrange),
),
child: Icon(Icons.arrow_left)),
SizedBox(width: 80),
TextButton(
onPressed: _onRightIndicatorPressed,
autofocus: false,
clipBehavior: Clip.none,
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.deepOrange),
),
child: Icon(Icons.arrow_right)),
],
),
/*
Text(
'(Count:$_counter: Code:$iCodeValue)',
style: Theme.of(context).textTheme.headline4,
textScaleFactor: 0.3,
),
SizedBox(height: 30),
Text('Select color to use: ', textScaleFactor: 2),
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(width: 30),
CircleColorPicker(
radius: 50,
thumbRadius: 6,
colorListener: (int value) {
setState(() {
currentColor = Color(value);
_incrementCounter();
});
},
Material(
// needed
color: Colors.transparent,
child: InkWell(
onTap: _onLeftIndicatorPressed, // Handle your callback.
splashColor: Colors.brown.withOpacity(0.5),
child: Ink(
height: 170.0 * 1.4,
width: 120.0 * 1.4,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/arrow_left.png'),
fit: BoxFit.cover,
),
),
),
),
),
Material(
// needed
color: Colors.transparent,
child: InkWell(
onTap:
_onRightIndicatorPressed, // Handle your callback.
splashColor: Colors.brown.withOpacity(0.5),
child: Ink(
height: 170.0 * 1.4,
width: 120.0 * 1.4,
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage('assets/images/arrow_right.png'),
fit: BoxFit.cover,
),
),
),
),
),
SizedBox(width: 60),
BarColorPicker(
cornerRadius: 10,
horizontal: false,
width: 100, // Height actually! (s.a.)
pickMode: PickMode.Grey,
colorListener: (int value) {
setState(() {
currentColor = Color(value);
_incrementCounter();
});
}),
]),
SizedBox(height: 10),
BarColorPicker(
width: 300,
thumbColor: Colors.white,
cornerRadius: 10,
pickMode: PickMode.Color,
colorListener: (int value) {
setState(() {
currentColor = Color(value);
_incrementCounter();
});
}),
SizedBox(height: 20),
Text('Brightness: ',
textScaleFactor: 2),
Slider(
min: 0,
max: 64,
divisions: 64,
value: dalpha,
label: '$dalpha',
onChanged: (double newValue) {
setState(() {
dalpha = newValue;
alpha = dalpha.truncate();
_incrementCounter();
});
},
Material(
// needed
color: Colors.transparent,
child: InkWell(
onTap: _onStopIndicatorPressed, // Handle your callback.
splashColor: Colors.brown.withOpacity(0.5),
child: Ink(
height: 170.0 * 1.4,
width: 120.0 * 1.4,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/stop.png'),
fit: BoxFit.cover,
),
),
),
),
),
*/
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _onStopIndicatorPressed,
tooltip: 'Stop',
child: Icon(Icons.stop),
), // This trailing comma makes auto-formatting nicer for build methods.
),
);
}

5
pubspec.yaml

@ -44,6 +44,11 @@ flutter:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# The path has to be specified relative to THIS pubspec.yaml!
assets:
- assets/images/arrow_left.png
- assets/images/arrow_right.png
- assets/images/stop.png
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.

Loading…
Cancel
Save