Compose desktop(JVM) BasicTextField, Korean input duplicating - compose-multiplatform

I'm implementing a simple search input field on Compose desktop.
My code looks as below.
BasicTextField(
modifier = Modifier.align(Alignment.CenterVertically).onPreviewKeyEvent {
if(it.key == Key.Enter && it.type == KeyEventType.KeyDown){
println("enter down: $textFieldState")
true
}else {
false
}
},
value = textFieldState,
onValueChange = { input ->
textFieldState = input
},
textStyle = TextStyle(
fontSize = 14.sp,
textAlign = TextAlign.Start,
fontWeight = FontWeight.Normal,
fontFamily = NotoSans,
color = Color.Black
),
maxLines = 1,
decorationBox = { innerTextField ->
Row(modifier = Modifier.fillMaxWidth()) {
if (textFieldState.isEmpty()) {
Text(
text = "Search with user name.",
fontSize = 14.sp,
color = Color(0xFF909ba9),
textAlign = TextAlign.Start,
fontWeight = FontWeight.Normal,
fontFamily = NotoSans,
modifier = Modifier.fillMaxWidth()
.align(Alignment.CenterVertically),
)
}
}
innerTextField()
}
)
This code will create a textfield which has 1 max lines.
It works without any problem on english inputs.
But when I type in Korean inputs, keys such as space, enter, or even numbers will duplicate the last Korean character. For example, in english, if I type in H, I, !,
it will be HII!.
Is there some locale settings that can be done to the textField?

I found no working solution in here or in the Compose multiplatform git issue page. I found a workaround using SwingPanel and JTextField.
SwingPanel(background = Color(0xFFf5f6f6), modifier = Modifier.fillMaxSize(), factory = {
//Some JTextfield I've obtaines from stackoverflow to show place holder text.
//Can be replaced to JTextField(columnCount:Int)
HintTextField("Enter in name",1).apply {
background = java.awt.Color(0xf5, 0xf6, 0xf6)
border = null
}
}, update = {
//SimpleDocumentListener is an implementation of DocumentListener.
//Which means it can be replaced by it.
it.document.addDocumentListener(object : SimpleDocumentListener{
override fun update(e: DocumentEvent) {
try{
val text = it.text
textFieldState = text
} catch(e : Exception) {
e.printStackTrace()
}
}
})
//I need an enter key to trigger some search logics.
//textFieldState seems to print the value as I intended
it.addKeyListener(object : KeyAdapter(){
override fun keyPressed(e: KeyEvent?) {
if(e?.keyCode == KeyEvent.VK_ENTER){
println("ENTER : $textFieldState")
}
}
})
})
Really hope the compose multiplatform team comes up with a better solution.

Related

How to get integer with regular expression in kotlin?

ViewModel
fun changeQty(textField: TextFieldValue) {
val temp1 = textField.text
Timber.d("textField: $temp1")
val temp2 = temp1.replace("[^\\d]".toRegex(), "")
Timber.d("temp2: $temp2")
_qty.value = textField.copy(temp2)
}
TextField
OutlinedTextField(
modifier = Modifier
.focusRequester(focusRequester = focusRequester)
.onFocusChanged {
if (it.isFocused) {
keyboardController?.show()
}
},
value = qty.copy(
text = qty.text.trim()
),
onValueChange = changeQty,
label = { Text(text = qtyHint) },
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = {
save()
onDismiss()
}
)
)
Set KeyboardType.Number, it display 1,2,3,4,5,6,7,8,9 and , . - space.
I just want to get integer like -10 or 10 or 0.
But I type the , or . or -(not the front sign), it show as it is.
ex)
typing = -10---------
hope = -10
display = -10---------
I put regular expression in
val temp2 = temp1.replace("[^\\d]".toRegex(), "")
But, it doesn't seem to work.
How I can get only integer(also negative integer)?
Use this regex (?<=(\d|-))(\D+) to replace all non digit characters, except first -.
fun getIntegersFromString(input: String): String {
val pattern = Regex("(?<=(\\d|-))(\\D+)")
val formatted = pattern.replace(input, "")
return formatted
}
Check it here

How would you go about placing boxes correctly

I am trying to make a datepicker with dates placed beneath the name of the days of the week. But I can't really get the spacing and the placement correct. don't really know what would make it possible to make the placement modifyable during run either because I mean if a month starts on a Wednesday the first date must align with Wednesday instead of Monday or well Sunday.
Here is my code:
val datesList = listOf<String>("Sun","Mon","Tue","Wed","Thu","Fri","Sat")
var dayCounter: Int = 1
var week: Int = 1
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
datesList.forEach {
Text(text = it.toString().substring(0,3))
}
}
while (dayCounter <= 31){
Row(modifier = Modifier.fillMaxWidth().padding(5.dp)) {
for (i in week..7){
if(dayCounter <= 31){
Box(contentAlignment = Alignment.Center, modifier = Modifier.background(Color.Red , CircleShape).padding(10.dp)) {
Text(text = dayCounter++.toString())
}
}
}
}
}
I have already tried with padding but that just stretches the boxes. and aspectratio wont work either because of the different amount of dates on each row. So I'm kinda stuck will someone please help?
I think this is what you want...
#Composable
fun DatePicker() {
val datesList = listOf<String>("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")
var dayCounter: Int = 1
var week: Int = 1
Column(Modifier.fillMaxWidth()) {
Row(
Modifier
.fillMaxWidth()
.padding(5.dp),
horizontalArrangement = Arrangement.Center
) {
datesList.forEach {
Box(
Modifier
.weight(1f)
.padding(5.dp),
contentAlignment = Alignment.Center
) {
Text(text = it.substring(0, 3))
}
}
}
var initWeekday = 3 // wednesday
while (dayCounter <= 31) {
Row(
Modifier
.fillMaxWidth()
.padding(5.dp),
) {
if (initWeekday > 0) {
repeat(initWeekday) {
Spacer(modifier = Modifier.weight(1f))
}
}
for (i in week..(7 - initWeekday)) {
if (dayCounter <= 31) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.weight(1f)
.background(Color.Red, CircleShape)
.padding(10.dp)
) {
Text(text = dayCounter++.toString())
}
} else {
Spacer(modifier = Modifier.weight(1f))
}
}
initWeekday = 0
}
}
}
}
Here's the result:

Endless/Carousel horizontal(Lazyrow) scrollview

I have made a lazyrow (horizontal) scroll with 10 items. My problem now is that when I scroll to item number 10, it stops. And I want it to go back to item number 1 again like a carousel. Does anyone know this? Here is my code for the 10 items:
//Horizontal Scroll view
item {
LazyRow {
items(10) { count->
Card(
modifier = Modifier
.width(110.dp)
.height(140.dp)
.padding(10.dp, 5.dp, 5.dp, 0.dp)
.clip(RoundedCornerShape(10.dp))
.background(Color.White),
elevation = 5.dp
) {
Column(
modifier = Modifier.padding(5.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Image(
painter = painterResource(id = hi.imageId),
contentDescription = "profile Image",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(60.dp)
.clip(CircleShape)
)
Spacer(modifier = Modifier.padding(5.dp))
Text(
text = hi.talk,
color = Color.Black,
fontWeight = FontWeight.Bold,
fontSize = 16.sp)
}
}
}
}
}
I'm pretty new to kotlin, so it is taking some fair time to learn. I couldn't find anything related to this in Jetpack Compose, and it is hard for me to convert from Java.

How to highlight a column programmatically in AMCharts 4?

In AMCharts version 3, there is a demo showing how to highlight a particular column.
Is this possible using AMCharts version 4? For example, in the Simple Column demo, highlight the UK column based on its value (ie, where country = 'UK').
I tried modifying the example at https://stackoverflow.com/a/54358490/906814 but I can't get a handle on the columns in order to assess their values and then apply the active state highlight (JSFiddle).
// copied from https://stackoverflow.com/a/54358490/906814 but not working yet
var activeState = series.columns.template.states.create("active");
activeState.properties.fill = am4core.color("#E94F37");
series.columns.each(function(column) {
alert("column") // no alert is seen
column.setState("active");
column.isActive = true;
})
There are two approaches you can take.
1) Use an adapter on the column's fill and stroke and check the column value before modifying the color, e.g.
series.columns.template.adapter.add('fill', function(fill, target) {
if (target.dataItem && target.dataItem.categoryX == "UK") {
return "#ff0000";
}
return fill;
});
series.columns.template.adapter.add('stroke', function(stroke, target) {
if (target.dataItem && target.dataItem.categoryX == "UK") {
return "#ff0000";
}
return stroke;
})
Demo
2) Use a property field and set the stroke and fill from your data:
chart.data = [
// ...
{
"country": "UK",
"value": 1122,
"color": "#ff0000"
},
// ...
];
// ...
series.columns.template.propertyFields.fill = "color";
series.columns.template.propertyFields.stroke = "color";
Demo

Problem in rendering Multiple Drilldown in fusioncharts

I am using Django. I want use the drilldown feature in fusioncharts. I am able to get the first drilldown correctly. But when I code for the second drilldown it is showing "No data to display". Also the following code renders all the charts in the same type. But I want to render the child charts in different types. I am sharing the snippet below.
def chart(request):
dataSource = {}
dataSource['chart'] = {
"caption": "Top 10 Most Populous Countries",
"showValues": "0",
"theme": "zune"
}
dataSource['data'] = []
dataSource['linkeddata'] = []
sbc = MTD.pdobjects.values('Vertical', 'Channel','Brand','Sales_Value')
sbc_df = sbc.to_dataframe().reset_index(drop=True)#Trying to use filtered model for dataframe
sbc_df['Sales_Value']=sbc_df['Sales_Value'].astype(float)
chn_gb=sbc_df.groupby('Channel')['Sales_Value'].sum().reset_index()
channel=list(chn_gb['Channel'])
channel_val=list(chn_gb['Sales_Value'])
sbc_gb=pandas.pivot_table(sbc_df,index=['Vertical','Channel'],values=['Sales_Value'],aggfunc='sum').reset_index()
brd_gb=pandas.pivot_table(sbc_df,index=['Vertical','Channel','Brand'],values=['Sales_Value'],aggfunc='sum').reset_index()
for i in range(len(channel)):
data = {}
data['label'] = channel[i]
data['value'] = channel_val[i]
data['link'] = 'newchart-json-'+ channel[i]
dataSource['data'].append(data)
linkData2 = {}
linkData2['id'] = channel[i]
linkedchart2 = {}
linkedchart2['chart'] = {
"caption" : "Top 10 Most Populous Cities - " + channel[i] ,
"showValues": "0",
"theme": "fusion",
}
linkedchart2['data'] = []
sbc_filtered=sbc_gb[sbc_gb.Channel == channel[i]]
vertical_list=list(sbc_filtered['Vertical'])
vertical_val=list(sbc_filtered['Sales_Value'])
for k in range(len(sbc_filtered)):
arrDara2 = {}
arrDara2['label'] = vertical_list[k]
arrDara2['value'] = vertical_val[k]
arrDara2['link'] = 'newchart-json-'+ vertical_list[k]
linkedchart2['data'].append(arrDara2)
linkData1 = {}
# Inititate the linkData for cities drilldown
linkData1['id'] = vertical_list[k]
linkedchart1 = {}
linkedchart1['chart'] = {
"caption" : "Top 10 Most Populous Cities - " + vertical_list[k] ,
"showValues": "0",
"theme": "fusion",
}
linkedchart1['data'] = []
brd_filtered=brd_gb[(brd_gb.Channel == channel[i]) & (brd_gb.Vertical== vertical_list[k])]
brd_list=list(brd_filtered['Brand'])
brd_val=list(brd_filtered['Sales_Value'])
for j in range(len(brd_filtered)):
arrDara1 = {}
arrDara1['label'] = brd_list[j]
arrDara1['value'] = brd_val[j]
linkedchart1['data'].append(arrDara1)
linkData1['linkedchart'] = linkedchart1
dataSource['linkeddata'].append(linkData1)
linkData2['linkedchart'] = linkedchart2
dataSource['linkeddata'].append(linkData2)
print(dataSource)
column2D = FusionCharts("column2D", "ex1" , "700", "400", "chart-1", "json", dataSource)
return render(request, 'table.html',{'output':column2D.render()})
Kindly help me to achieve the successive drilldown correctly.
Thanks
In order to change the chart type for the child chart you need to use configureLink API method to set the child chart type, you can also set different chart at a different level, provided the datastructure for each chart is correct, here is how you can do
myChart.configureLink([
{ type: 'bar2d' },
{ type: 'line' },
{ type: 'pie2d' }
]);
Here is a demo - http://jsfiddle.net/x0c2wo7k/
Please note the above sample is using plain javascript