How to pass variable content to a parameter value in dart/flutter? - oop

I may be missing something obvious, but I'm having trouble passing a variable to a parameter or widget in flutter/dart. For example, let's say I have some variable:
String col = 'red';
and I want to pass this to a color parameter to get the equivalent of
color: Colors.red
The difficult thing is that any way I try to pass the value ends up passing a string (which isn't accepted), including trying to pass just the value of col directly or trying to build a function that returns Colors.col.
I think what I need is something like a function like
setColor(String str) {
return Colors.str;
}
but, as you might expect, this returns "The getter 'str' isn't defined for the type 'Colors'." (And similarly for:
setColor(String str) {
return Colors.$str;
}
I know one option is to create a function using a bunch of if's, like
setColor(String str) {
if (str==red) return Colors.red;
if (str==blue) return Colors.blue;
if (str==green) return Colors.green;
etc.
}
but I'd prefer a more elegant option if one is available.
EDIT: It looks like this isn't quite as easy as I'd hoped (see answers and comments to answers below).

The library Supercharged is your best solution. You can try it this way (Hex text or HTML color):
"#ff00ff".toColor(); // pink
"ff0000".toColor(); // red
"00f".toColor(); // blue
"red".toColor(); // red (HTML color name)
"deeppink".toColor(); // deep pink (HTML color name)
Of course, this function depends on extension. Extension methods, introduced in Dart 2.7.
Edit:
extension MainAxisAlignmentExtension on String {
MainAxisAlignment get mainAxis {
switch (this.toUpperCase()) {
case "BETWEEN":
return MainAxisAlignment.spaceBetween;
case "AROUND":
return MainAxisAlignment.spaceAround;
case "EVENLY":
return MainAxisAlignment.spaceEvenly;
case "CENTER":
return MainAxisAlignment.center;
case "START":
return MainAxisAlignment.start;
case "END":
return MainAxisAlignment.end;
default:
return MainAxisAlignment.start;
}
}
}
print("Between".mainAxis);
print("AROUND".mainAxis);

Instead of passing Color as String, you can use type Color
Color col = Colors.red;
If you want to continue using String to store color you can use the hex value
String col = "#FF5733";
And use a function to convert it to color
Color hexToColor(String code) {
return new Color(int.parse(code.substring(1, 7), radix: 16) + 0xFF000000);
}
Example:
Color newColor = hexToColor(col);
Hope this is what you are looking for!

You can pass colors from one widget to another by declaring color as a variable.
final Color redColor=Colors.red;
Then you can pass it to a widget as an argument (Passing color to a widget):
Widget something(Color redColor){
Text("It Works!",style: TextStyle(color: redColor))
}
If you want to pass it from one stateless or stateful widget to another:
class DetailScreen extends StatelessWidget {
// Declare a field that holds the color.
final Color redColor;
// In the constructor, require a Color.
DetailScreen({Key key, #required this.redColor}) : super(key: key);
// Your widget build and other things here
}
Then get the value by calling:
Text("It Works!",style: TextStyle(color: widget.redColor))

Related

Custom language plugin - braces alignment when returning an object

I am developing a plugin for IntelliJ IDEA which supports my custom Lua-based language formatting.
I expect to get following result
func () {
//do something
return {
data = {
v1 = "some value",
v2 = 123
}
}
}
But I am getting this:
func () {
//do something
return {
data = {
v1 = "some value",
v2 = 123
}
}
}
The issue is that the closing braces after return statement are getting aligned with the opening.
To align braces in a Java style I tried most obvious combinations of indents and wrappings but with no luck.
I have not implemented any Code Style Settings for my language but when debugging I see that CommonSettings contains HTML, XML, JAVA and JSON CommonCodeStyleSettings.
Cleaning up myCommonSettingsMap and myCustomSettingsMap in bebugger did not remedy the situation.
I assume some default settings are involved but I have no idea what to check. Could somebody help me?
I have found the answer at IntelliJ forum: How to make the Indent relative to direct parent's parents?
In my code I always used a default Alignment:
Block block = new Simplek(child, Wrap.createWrap(WrapType.NONE, false),
Alignment.createAlignment(), spacingBuilder);
The solution is to pass null when alignment is not needed.

Kotlin map a string to another type?

In swift, I can do
"Some String".map { SomeObject($0) }
In kotlin it seems like the string is treated as a char array so the result is the map of each character. Is it possible to get similar behavior like the swift code I posted?
"Some String".map { SomeObject(it) }
You can accomplish something like that with let:
"Some String".let { SomeObject(it) }
If you have an appropriate constructor in place (e.g. constructor(s : String) : this(...)) you can also call it as follows:
"Some String".let(::SomeObject)
run and with work also, but are usually taken if you want to rather call a method of the receiver on it. Using run/with for this would look as follows:
"Some String".run { SomeObject(this) }
with ("Some String") { SomeObject(this) }
// but run / with is rather useful for things like the following (where the shown function calls are functions of SomeObject):
val x = someObject.run {
doSomethingBefore()
returningSomethingElse()
}
Besides using let, run or with, you can also write an extension method:
fun String.toSomeObject() = SomeObject(this)
Then use it like follows:
"SomeObject".toSomeObject()

Why .map on a mutableList doesn't actually change values inside of List in Kotlin?

This is what I have and what I want to achieve:
I have a class which has a mutableList as a field.
I want to find a specific element inside that list and change it.
This is what I've tried so far:
This is the functional statement I was hoping would have worked, after I've also put it in an Extension function:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
this.students.filter { l -> l.id == id }
.map { l -> l.name = modifiedName }
.toList()
}
But the list students appears to be unchanged after this function is called.
I found an "ugly" solution with the code below:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
for (l : Student in this.students) {
if (l.id == id) {
l.name = modifiedName
break
}
}
}
Still tho, I'd really like to know why the first block of code behaves like it does and doesn't actually have any effect on the list.
You can think of map as a way to transform input to get new output. Normally it should not mutate state inside, in other words it should be a function without side effects to pursue maintainability
In your case you clearly want to mutate elements, for that you might want to use that code snippet:
fun Classroom.setNewParameters(id: String, modifiedName: String) {
this.students.filter { l -> l.id == id }
.onEach { l -> l.name = modifiedName }
}
Also, even you used map incorrectly it should must modify field l.name (unless you have implemented you own delegates or getter/setter). Try to debug set breakpoint on this.students.filter { l -> l.id == id } and see if there are any items left after filtering
Noob here but I did just see something related to this the other day.
Is there a reason you wouldn't just check to see if your array contains the old value, return the element id and then assign your new value to that id?
I guess I'm just pointing out that this could be accomplished with a "value in array" type search... but I'm still too new to know the pros and cons of using it vs map.
Kind of like this below, which I got from Kotlin - Idiomatic way to check array contains value
"value" in array
Which translates into the Java API:
array.contains("value")
So I'd check for the old value in the array, return it's index and then reassign that index with the new value.

How do I check if Geb Module "content" is present?

I'm a bit new to the whole Selenium/Geb thing, so I'm probably going about this a bit wrong, but I'm trying to get the exists() method in the following code to work properly.
class Question extends Module {
static base = { $("fieldset") }
static content = {
input { $("input[type=text]") }
name { input.getAttribute("name").toString() }
}
boolean exists() {
return input.isPresent()
}
Frustratingly, when I try to execute that code (from a Spock Test, "go"ing to a PageObjectm including this module, I get the following:
The required page content 'input - SimplePageContent (owner: question - Question (owner: MyPage, args: [], value: null), args: [], value: null)' is not present
I've tried a number of other things, including:
if (input) return true; return false,
... input.size() == 0,
Using static at = {...} (doesn't seem to be supported for modules"
Any ideas
By default Geb ensures that your content definitions return non empty elements. If your content is optional you can tell it using required content option:
name(required: false) { input.getAttribute("name").toString() }
Because Geb utilizes Groovy Truth to redefine how navigator are coerced to boolean values(empty navigators are falsey and non-empty are truthy) you can simplify your exists method to:
boolean exists() {
input
}

How to avoid if else or switch case whe dealing with enums?

I have a member variable that tells units for a value I have measured like centimeters,kilometers,seconds,hours etc.
Now these are enums,
When I display a corresponding string, I have created a method that returns corresponding string for these enums.
Unlike Java, enums here cant have other properties associated with them.
So I have to explicitly do a if-else-if chain or a switch case to return the correct string.
I am new to Objective C. any good practice that I should be following in such scenarios ?
afaik Objective-C enums are just old-school C enums... so maybe you can use an integer value for them?
I guess if your enum values started at 0 and increased you could use some sort of array access:
const char *distanceUnitToString2(enum DistanceUnit unit)
{
const char *values[] = {
"cm",
"m",
"km"
};
// do some sanity checking here
// ...
return values[unit];
}
But this feels a little flaky to me. What if you have negative values, or you are using bitmask-style enum values like 1 << 8? You are going to end up using a very large array.
You also could use a switch and improve it a little with a macro. Something like this:
const char *distanceUnitToString(enum DistanceUnit unit)
{
#define CASE(UNIT, STRING) case (UNIT): return (STRING)
switch (unit) {
CASE(kCentimeters, "cm");
CASE(kMeters, "m");
CASE(kKiloMeters, "km");
default:
// should not get here
assert(0);
break;
}
#undef CASE
}
But you don't really save that much vs. not using the macro.
Martin James's comment is the right answer. And use a definition of the enum like:
enum units { cm = 0, m, km };
that way you can be sure that your enum translates to the correct index values.