Skip to content

Commit

Permalink
feat: barchart (#99)
Browse files Browse the repository at this point in the history
* feat: barchart

* feat: dot chart

* feat: pos/neg chart

* fix: send events from proper context

Co-authored-by: Vittorio Cellucci <vel@qlik.com>
  • Loading branch information
vcellu and vcellu committed Oct 29, 2022
1 parent 935d378 commit ac7ab23
Show file tree
Hide file tree
Showing 21 changed files with 535 additions and 32 deletions.
Expand Up @@ -28,6 +28,8 @@ public class CellView extends LinearLayout implements SelectionsObserver {
content = new ClickableTextView(context, selectionsEngine, scrollView);
} else if(type.equals("image")) {
content = new ClickableImageView(context, selectionsEngine, scrollView, this);
} else if(type.equals("miniChart")) {
content = new MiniChartView(context);
}
this.scrollView = scrollView;
this.selectionsEngine = selectionsEngine;
Expand Down Expand Up @@ -95,7 +97,7 @@ public void onClear() {

public void onRecycled() {
DataCell cell = content.getCell();
if (cell.isDim) {
if (cell != null && cell.isDim) {
selectionsEngine.remove(this);
}
}
Expand Down
Expand Up @@ -95,7 +95,7 @@ private void fitToWidth(DataColumn column, Bitmap image) {
}

public void setSizing(DataColumn column, Bitmap image) {
switch (column.imageSize) {
switch (column.representation.imageSize) {
case "alwaysFit":
alwaysFit();
break;
Expand All @@ -116,7 +116,7 @@ public void setAlignment(DataColumn column) {
LinearLayout wrapper = (LinearLayout) container.getParent();
setTranslationY(0);

switch (column.imagePosition) {
switch (column.representation.imagePosition) {
case "topCenter":
wrapper.setGravity(Gravity.LEFT);
break;
Expand Down
Expand Up @@ -3,6 +3,7 @@
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;

import java.util.List;
Expand Down Expand Up @@ -36,7 +37,8 @@ public void autoSize(CustomHorizontalScrollView contextView) {

if (resized) {
requestLayoutHeaderView();
EventUtils.sendOnColumnResize(contextView, this.columnList);
FrameLayout parent = (FrameLayout)contextView.getParent();
EventUtils.sendOnColumnResize(parent, this.columnList);
}
}

Expand Down
Expand Up @@ -3,6 +3,8 @@
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
Expand Down Expand Up @@ -70,7 +72,8 @@ public void onScrolled(@NonNull RecyclerView rv, int dx, int dy) {
&& dataProvider.needsMore()) {
// start the fetch
dataProvider.setLoading(true);
EventUtils.sendEventToJSFromView(scrollView, "onEndReached");
FrameLayout parent = (FrameLayout) scrollView.getParent();
EventUtils.sendEventToJSFromView(parent, "onEndReached");
}
}
}
Expand Down
Expand Up @@ -23,6 +23,7 @@ public class DataCell {
int rawColIdx;
boolean isNumber;
int textGravity = Gravity.LEFT;
qMiniChart miniChart;
public DataCell(ReadableMap source, DataColumn column) {
qText = source.getString("qText");
qElemNumber = source.getInt("qElemNumber");
Expand Down Expand Up @@ -51,6 +52,7 @@ public DataCell(ReadableMap source, DataColumn column) {
DataProvider.addImagePath(imageUrl);
}
}
miniChart = source.hasKey("qMiniChart") ? new qMiniChart(source.getMap("qMiniChart")) : null;

}

Expand Down
Expand Up @@ -16,25 +16,19 @@ public class DataColumn {
public Boolean isDim = false;
public int width = 200;
public String label;
public String type;
public String id;
public String align;
public String sortDirection;
public String imageUrl;
public String imageSize;
public String imagePosition;
public Representation representation;
public List<Object> stylingInfo;
public int dataColIdx = 0;
public boolean active = false;

public DataColumn(ReadableMap source) {
ReadableMap representation = source.getMap("representation");
ReadableMap representationMap = source.getMap("representation");
representation = new Representation(representationMap);
stylingInfo = source.getArray("stylingInfo").toArrayList();
type = representation.getString("type");
imageUrl = representation.getString("imageUrl");
imageSize = representation.getString("imageSize");
imagePosition = representation.getString("imagePosition");
imageSize = representation.getString("imageSize");

isDim = source.getBoolean("isDim");
width = source.getInt("width");
label = source.getString("label");
Expand Down
Expand Up @@ -152,16 +152,16 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int
int width = column.width;
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(width, TableTheme.rowHeight);

if (column.type.equals("image")) {
if (column.representation.type.equals("image")) {
RelativeLayout wrapper = new RelativeLayout(parent.getContext());

// RelativeLayout container = new RelativeLayout(parent.getContext());

CellView cellView = new CellView(parent.getContext(), "image", this.selectionsEngine, this.scrollView);
RelativeLayout.LayoutParams cellLayoutParams = new RelativeLayout.LayoutParams(-1,-1);
// container.addView(cellView);
wrapper.addView(cellView, cellLayoutParams);
rowView.addView(wrapper, layoutParams);
} else if(column.representation.type.equals("miniChart")) {
CellView cellView = new CellView(parent.getContext(), "miniChart", this.selectionsEngine, this.scrollView);

rowView.addView(cellView);
} else {
CellView cellView = new CellView(parent.getContext(), "text", this.selectionsEngine, this.scrollView);
ClickableTextView textView = (ClickableTextView) cellView.content;
Expand Down Expand Up @@ -294,7 +294,8 @@ public void onViewRecycled(RecyclerView.ViewHolder viewHolder) {
}

public void onEndPan(CustomHorizontalScrollView contextView) {
EventUtils.sendOnColumnResize(contextView, dataColumns);
FrameLayout parent = (FrameLayout) contextView.getParent();
EventUtils.sendOnColumnResize(parent, dataColumns);
}

}
Expand Up @@ -3,6 +3,7 @@
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
Expand All @@ -15,23 +16,23 @@
import java.util.List;

public class EventUtils {
public static void sendEventToJSFromView(CustomHorizontalScrollView contextView, String eventName) {
public static void sendEventToJSFromView(FrameLayout contextView, String eventName) {
if (contextView != null) {
WritableMap event = Arguments.createMap();
ReactContext context = (ReactContext) contextView.getContext();
// here the documentation is still using the old receiveEvent, so not sure what to use????
context.getJSModule(RCTEventEmitter.class).receiveEvent(contextView.getId(), eventName, event);
}
}
public static void sendEventToJSFromView(CustomHorizontalScrollView contextView, String eventName, WritableMap event) {
public static void sendEventToJSFromView(FrameLayout contextView, String eventName, WritableMap event) {
if (contextView != null) {
ReactContext context = (ReactContext) contextView.getContext();
// here the documentation is still using the old receiveEvent, so not sure what to use????
context.getJSModule(RCTEventEmitter.class).receiveEvent(contextView.getId(), eventName, event);
}
}

public static void sendOnColumnResize(CustomHorizontalScrollView contextView, List<DataColumn> dataColumns) {
public static void sendOnColumnResize(FrameLayout contextView, List<DataColumn> dataColumns) {
WritableArray widths = Arguments.createArray();
for(int i = 0; i < dataColumns.size(); i++) {
widths.pushDouble(PixelUtils.pxToDp(dataColumns.get(i).width));
Expand All @@ -41,7 +42,7 @@ public static void sendOnColumnResize(CustomHorizontalScrollView contextView, Li
EventUtils.sendEventToJSFromView(contextView, "onColumnsResized", event);
}

public static void sendOnHeaderTapped(CustomHorizontalScrollView contextView, DataColumn column) {
public static void sendOnHeaderTapped(FrameLayout contextView, DataColumn column) {
WritableMap event = Arguments.createMap();
try {
String columnJSONString = column.toEvent();
Expand Down
Expand Up @@ -4,6 +4,7 @@
import android.content.Context;
import android.graphics.Color;
import android.view.MotionEvent;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;

Expand Down Expand Up @@ -42,12 +43,13 @@ public void handleSingleTap() {
if(column.sortDirection == null && column.active) {
return;
}
EventUtils.sendOnHeaderTapped(scrollView, column);

FrameLayout parent = (FrameLayout)scrollView.getParent();
EventUtils.sendOnHeaderTapped(parent, column);

}

public void handleDown() {
if(column.sortDirection == null && column.active) {
if(column.sortDirection == null && column.active) {
return;
}
this.setBackgroundColor(Color.LTGRAY);
Expand Down
@@ -0,0 +1,29 @@
package com.qliktrialreactnativestraighttable;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;

public class MiniBarChartRenderer extends MiniChartRenderer {

Rect bar = new Rect();

public MiniBarChartRenderer(qMiniChart chartData, Representation representation) {
super(chartData, representation);
}

@Override
public void render(Canvas canvas) {
float x = padding + (horizontalPadding / 2.0f);
paint.setColor(miniChartInfo.colors.main.color);
for(int i = 0; i < miniChartData.matrix.rows.size(); i++) {
float value = (float) miniChartData.matrix.rows.get(i).columns.get(1).qNum;
float height = value * scale;
float y = xAxis - height ;
float b = xAxis;
setColor(i, value, miniChartData.matrix.rows.size());
canvas.drawRect(x, y, x + bandwidth, b, paint);
x += padding * 2.0f + bandwidth;
}
}
}
@@ -0,0 +1,66 @@
package com.qliktrialreactnativestraighttable;

import android.graphics.Color;

import com.facebook.react.bridge.ReadableMap;

public class MiniChartInfo {
public String type;
public Boolean showDots;
public YAxis yAxis;
public ChartColors colors;

class YAxis {
public String position;
public String scale;
public YAxis(ReadableMap data) {
position = data.hasKey("position") ? data.getString("position") : "";
scale = data.hasKey("scale") ? data.getString("scale") : "";
}
}

class MiniChartColor {
public String colorValue;
public int index;
int color;
boolean valid = false;
public MiniChartColor(ReadableMap data) {
colorValue = data.hasKey("color") ? data.getString("color") : "none";
index = data.hasKey("index") ? data.getInt("index") : 0;
if(!colorValue.equals("none")) {
color = Color.parseColor(colorValue);
valid = true;
}
}
}

class ChartColors {
public MiniChartColor first;
public MiniChartColor last;
public MiniChartColor min;
public MiniChartColor max;
public MiniChartColor negative;
public MiniChartColor positive;
public MiniChartColor main;
public ChartColors(ReadableMap data) {
first = getMiniChartColor("first", data);
last = getMiniChartColor("last", data);
min = getMiniChartColor("min", data);
max = getMiniChartColor("max", data);
negative = getMiniChartColor("negative", data);
positive = getMiniChartColor("positive", data);
main = getMiniChartColor("main", data);
}

MiniChartColor getMiniChartColor(String name, ReadableMap data) {
return data.hasKey(name) ? new MiniChartColor(data.getMap(name)) : null;
}
}

MiniChartInfo(ReadableMap data) {
type = data.hasKey("type") ? data.getString("type") : "";
showDots = data.hasKey("showDots") ? data.getBoolean("showDots") : false;
yAxis = data.hasKey("yAxis") ? new YAxis(data.getMap("yAxis")) : null;
colors = data.hasKey("colors") ? new ChartColors(data.getMap("colors")) : null;
}
}
@@ -0,0 +1,79 @@
package com.qliktrialreactnativestraighttable;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;

public class MiniChartRenderer {
qMiniChart miniChartData = null;
MiniChartInfo miniChartInfo = null;
Representation representation = null;
Rect bounds = new Rect();
Paint paint = new Paint();
float horizontalPadding = 20.0f;
float verticalPadding = 8.0f;
float bandwidth = 0.0f;
float padding = 0.0f;
float scale = 0.0f;
float yScale = 1.0f;
float xAxis = 0.0f;

public MiniChartRenderer(qMiniChart chartData, Representation representation ) {
this.representation = representation;
miniChartData = chartData;
miniChartInfo = representation.miniChart;
paint.setColor(Color.RED);


}

public void updateData(qMiniChart chartData, Representation representation) {
miniChartData = chartData;
this.representation = representation;
}

public void resetScales(Rect bounds) {
this.bounds = bounds;
if(miniChartData != null) {
if(miniChartInfo.yAxis != null && miniChartInfo.yAxis.scale.equals("global")) {
float min = Math.min((float) representation.globalMin, 0.0f);
yScale = (float) representation.globalMax - min;
} else {
float min = Math.min((float) miniChartData.qMin, 0.0f);
yScale = (float) (miniChartData.qMax - min);
}
setBandwidth();
setScales();
}
}

protected void setBandwidth() {
float width = bounds.width() - horizontalPadding;
float totalBandWidth = width / miniChartData.matrix.rows.size();
bandwidth = totalBandWidth * 0.8f;
padding = totalBandWidth * 0.1f;
}

protected void setScales() {
float height = bounds.height() - (verticalPadding * 2.0f);
scale = height / yScale;
xAxis = miniChartData.qMin < 0.0 ? (float)bounds.height() + ((float)miniChartData.qMin * scale) : bounds.height();
}

protected void setColor(int index, float value, int count) {
if(miniChartInfo.colors.max.valid && value == (float) miniChartData.qMax) {
paint.setColor(miniChartInfo.colors.max.color);
} else if(miniChartInfo.colors.min.valid && value == (float) miniChartData.qMin) {
paint.setColor(miniChartInfo.colors.min.color);
} else if(miniChartInfo.colors.first.valid && index == 0) {
paint.setColor(miniChartInfo.colors.first.color);
} else if(miniChartInfo.colors.last.valid && index == count - 1) {
paint.setColor(miniChartInfo.colors.last.color);
} else {
paint.setColor(miniChartInfo.colors.main.color);
}
}

public void render(Canvas canvas) {}
}

0 comments on commit ac7ab23

Please sign in to comment.