left-icon

Writing Native Mobile Apps in a Functional Language Succinctly®
by Vassili Kaplan

Previous
Chapter

of
A
A
A

CHAPTER 5

Adding Syncfusion Controls

Adding Syncfusion Controls


“Good artists copy, great artists steal.”

Pablo Picasso

In this chapter, we are going to see how to add controls not developed by us, but by someone else. As an example, I decided to use Syncfusion controls. Why?

  • They look really cool and are very similar on iOS and Android.
  • They are easy to use and configure.
  • They are easy to include in the CSCS Framework, making them look as a part of CSCS.
  • There is a Community License that allows free use of the Syncfusion framework, provided your revenue is below $1 million and there are up to five developers in your company that will be working with this framework.
  • Even the Community License includes email support.
  • I enjoy using free stuff. Don’t you? (If your revenue is more than $1 million or you have more than five developers, you will need to buy a license here).

It goes without saying that this book is published by Syncfusion not because I advertise their controls: they explicitly told me that I should use any product that fits this book the best.

Adding Syncfusion to the CSCS project

The easiest way to figure out how the Syncfusion controls work is to download the Syncfusion sample project. You can add the Syncfusion controls to your project in two different ways:

  • As DLLs from the sample project to the References section of your project.
  • As NuGet Packages via Your Project > Packages > Add Packages

Figure 8 shows how your Visual Studio project will look after adding the Syncfusion NuGet packages.

Syncfusion iOS and Android NuGet Packages (on macOS)

Figure 8: Syncfusion iOS and Android NuGet Packages (on macOS)

For using the controls, I created the SfWidget class in both Xamarin.iOS and Xamarin.Android. I didn’t want to put the common class into the shared project since there are too many differences between the iOS and Android Syncfusion implementations (for example, SFBarcode on iOS versus SfBarcode on Android, and so on).

So I added all of the Syncfusion widgets to the SfWidget class, deriving from the iOSVariable class on iOS, and from the DroidVariable class on Android. A fragment of the iOS version is shown in Code Listing 23. The Android version looks very similar.

Code Listing 23: A Fragment of the SfWidget Class on iOS

public class SfWidget : iOSVariable
{
  SyncFusionType  m_type;
  SFBarcode       m_barcode;

  SFDigitalGauge  m_digitalGauge;
  SFCircularGauge m_circularGauge;
  SFCircularScale m_circularScale;
  SFNeedlePointer m_needlePointer;
  SFRangePointer  m_rangePointer1, m_rangePointer2;
  SFNumericUpDown m_stepper;
  SFBusyIndicator m_busyIndicator;
  SfPicker        m_picker;
  SFChart         m_chart;

  SfDataGrid      m_grid;
  int             m_rowIndex;
  DataModel       m_model;
  UIView          m_detailView;

  string          m_data;
  CGRect          m_rect;

  List<string>    m_strings;
  List<UIImage>   m_pics;

  UITextAlignment m_alignment = UITextAlignment.Left;
  UIColor m_bgColor           = UIColor.Clear;
  UIColor m_fontColor         = UIColor.Black;

  static bool     m_init;

  public enum SyncFusionType {
    NONE, QR_BARCODE, CODE39_BARCODE, CIRCULAR_GAUGE, DIGITAL_GAUGE,

    STEPPER, BUSY_INDICATOR,PICKER, SPLINE_GRAPH, DOUGHNUT_GRAPH, DATA_GRID
  };

  public SyncFusionType SfType { getset; }

  public SfWidget(SyncFusionType type, string name, string text,

                  CGRect rect) :
      base(UIType.CUSTOM, name)
  {
    m_type = type;
    m_data = text;
    m_rect = rect;
    SfType = type;
    switch (type) {
      case SyncFusionType.BUSY_INDICATOR:
        CreateBusyIndicator();
        break;
      case SyncFusionType.QR_BARCODE:
        CreateQRBarcode();
        break;
      case SyncFusionType.CODE39_BARCODE:
        CreateCode39Barcode();
        break;
      case SyncFusionType.PICKER:
        CreatePicker();
        break;
      case SyncFusionType.STEPPER:
        CreateStepper();
        break;
      case SyncFusionType.CIRCULAR_GAUGE:
        CreateCircularGauge();
        break;
      case SyncFusionType.DIGITAL_GAUGE:
        CreateDigitalGauge();
        break;
      case SyncFusionType.DATA_GRID:
        CreateDataGrid();
        break;
      case SyncFusionType.DOUGHNUT_GRAPH:
      case SyncFusionType.SPLINE_GRAPH:
        CreateGraph();
        break;
    }
    ViewX.Tag = ++m_currentTag;
  }
  public override Variable Clone()
  {
    SfWidget newVar = (SfWidget)this.MemberwiseClone();
    return newVar;
  }

  public override iOSVariable GetWidget(string widgetType,

           string widgetName, string initArg, CGRect rect)
  {
    switch (widgetType) {
      case "SfQRBarcode":
        return new SfWidget(SfWidget.SyncFusionType.QR_BARCODE,

                            widgetName, initArg, rect);
      case "SfCode39Barcode":
        return new SfWidget(SfWidget.SyncFusionType.CODE39_BARCODE,

                            widgetName, initArg, rect);
      case "SfCircularGauge":
        return new SfWidget(SfWidget.SyncFusionType.CIRCULAR_GAUGE,

                            widgetName, initArg, rect);
      case "SfDigitalGauge":
        return new SfWidget(SfWidget.SyncFusionType.DIGITAL_GAUGE,

                            widgetName, initArg, rect);
      case "SfStepper":
        return new SfWidget(SfWidget.SyncFusionType.STEPPER,

                            widgetName, initArg, rect);
      case "SfBusyIndicator":
        return new SfWidget(SfWidget.SyncFusionType.BUSY_INDICATOR,

                            widgetName, initArg, rect);
      case "SfDataGrid":
        return new SfWidget(SfWidget.SyncFusionType.DATA_GRID,

                            widgetName, initArg, rect);
      case "SfDoughnutGraph":
        return new SfWidget(SfWidget.SyncFusionType.DOUGHNUT_GRAPH,

                            widgetName, initArg, rect);
      case "SfSplineGraph":
        return new SfWidget(SfWidget.SyncFusionType.SPLINE_GRAPH,

                            widgetName, initArg, rect);
      case "SfPicker":
        return new SfWidget(SfWidget.SyncFusionType.PICKER,

                            widgetName, initArg, rect);
    }
    return null;
  }

I registered all the Syncfusion controls and related functions within the CustomInit class; see Code Listing 5. I informed the parser that it needs to look for a particular type of a widget in this statement in CustomInit:

UIVariable.WidgetTypes.Add(new SfWidget());

Next, let’s look at some of the Syncfusion controls.

Stepper or Numeric Up Down

Figure 9 contains a screenshot of a stepper (or a Numeric Up Down, in Syncfusion terms). There are three kinds of steppers, depending on the stepper configuration: the buttons could be either on the left, right, or on both sides of the widget. They look somewhat different when the buttons are on both sides of the widget—in iOS, + precedes -. I guess this is more the iOS style.

Syncfusion Stepper on iOS and Android

Figure 9: Syncfusion Stepper on iOS and Android

The controls in Figure 9 were created using the following CSCS script:

locStepper1 = GetLocation("ROOT""CENTER""ROOT""CENTER");
AddSfStepper(locStepper1, "stepper1""70:10:120:5"30060);
SetValue(stepper1, "buttons""both");

locStepper2 = GetLocation("ROOT""CENTER", stepper1, "BOTTOM"010);
AddSfStepper(locStepper2, "stepper2""70:10:120:5"30060);
SetValue(stepper2, "buttons""left");

locStepper3 = GetLocation("ROOT""CENTER", stepper2, "BOTTOM"010);
AddSfStepper(locStepper3, "stepper3""70:10:120:5"30060);
SetValue(stepper3, "buttons""right");

The "70:10:120:5" initialization means that 70 is the default value, the minimum is 10, the maximum is 120, and the step is 5. This is just a shortcut; you can do the same with these separate CSCS statements:

SetValue(stepper, "value",  70); or SetValue(stepper, 70);
SetValue(stepper, "min",    10);
SetValue(stepper, "max",    120);
SetValue(stepper, "step",   5);

To get the current value of the stepper, use the following statement:

stepperValue = GetValue(stepper);

You can also subscribe to an event of the user by pressing a plus or minus button:

AddAction(stepper, "stepper_clicked");
function stepper_clicked(sender, arg)
{
// arg contains the current stepper value.
}

Now let’s see the stepper’s implementation. As follows from Code Listing 23, the CreateStepper() method is called in case of a stepper. It is shown in Code Listing 24.

Code Listing 24: The Implementation of the CreateStepper Method

void CreateStepper()
{
  m_stepper = new SFNumericUpDown();
  m_stepper.Frame = m_rect;

  double minValue = 0, maxValue = 1, currValue = 0, step = 1.0;
  Utils.Extract(m_data, ref currValue, ref minValue,

                        ref maxValue, ref step);
  m_stepper.AllowNull = true;
  m_stepper.PercentDisplayMode = SFNumericUpDownPercentDisplayMode.Value;
  m_stepper.ValueChangeMode = SFNumericUpDownValueChangeMode.OnLostFocus;
  m_stepper.Value = (nfloat)currValue;
  m_stepper.StepValue = (nfloat)step;
  m_stepper.Minimum = (nfloat)minValue;
  m_stepper.Maximum = (nfloat)maxValue;
  m_stepper.Culture = NSLocale.CurrentLocale;

  m_stepper.ValueChanged += (sender, e) =>  {
    ActionDelegate?.Invoke(WidgetName, e.Value.ToString());
  };

  ViewX = m_stepper;
}

That’s it—as you can see, the C# implementation is pretty compact, since the rest was done by the good people at Syncfusion.

To be able to use the generic SetValue() CSCS function, the iOSVariable.SetValue() function for iOS, and the DroidVariable.SetValue() function for Android, must be overridden. A fragment of the SfWidgetSetValue() function for the stepper is shown in Code Listing 25.

Code Listing 25: A Fragment of the SfWidget.SetValue Method

public override bool SetValue(string value1, string value2 = "")
{
  double valueNum = Utils.ConvertToDouble(value2);

  if (m_stepper != null) {
    switch (value1) {
      case "min":
        m_stepper.Minimum   = (nfloat)valueNum;
        break;
      case "max":
        m_stepper.Maximum   = (nfloat)valueNum;
        break;
      case "step":
        m_stepper.StepValue = (nfloat)valueNum;
        break;
      case "value":
        m_stepper.Value     = (nfloat)valueNum;
        break;
      case "buttons":
        switch(value2) {
          case "left": m_stepper.SpinButtonAlignment =

                       SFNumericUpDownSpinButtonAlignment.Left;
            break;
          case "right":
            m_stepper.SpinButtonAlignment =

                      SFNumericUpDownSpinButtonAlignment.Right;
            break;
          default: m_stepper.SpinButtonAlignment =

                      SFNumericUpDownSpinButtonAlignment.Both;
            break;
        }
        break;
      }
    }

  }

 // Other Syncfusion Widgets.

}

You can also set up custom icons instead of the + and - buttons, but this is out of our scope.

QR barcode

A QR (“Quick Response”) barcode is a form of a two-dimensional machine-readable matrix. It is often used to code website addresses. There is also a Syncfusion control that creates these codes. Check out an example of applying the QR code to the Google website in Figure 10.

Syncfusion QR Barcode for www.google.com

Figure 10: Syncfusion QR Barcode for www.google.com

The QR barcode in Figure 10 was created using the following CSCS code:

locSFWidget = GetLocation("ROOT""CENTER""ROOT""CENTER");
AddSfQRBarcode(locSFWidget,  "QRBarcode""http://www.google.com"450450);

You can also set the QR code in a separate CSCS statement, for example:

SetText(QRBarcode, "http://www.iLanguage.ch");

The C# implementation is very compact as well; see Code Listing 26.

Code Listing 26: The Implementation of the CreateQRBarcode Method

void CreateQRBarcode()
{
  m_barcode = new SFBarcode();
  m_barcode.Frame = m_rect;

  m_barcode.BackgroundColor = UIColor.Clear;
  m_barcode.Text = (NSString)m_data;
  m_barcode.Symbology = SFBarcodeSymbolType.SFBarcodeSymbolTypeQRCode;
  SFQRBarcodeSettings settings = new SFQRBarcodeSettings();
  settings.XDimension = 5;
  m_barcode.SymbologySettings = settings;

  ViewX = m_barcode;
}

 

Barcode 39

Code 39 is a one-dimensional barcode used to code uppercase words, numbers, and some special characters. It can be used to code prices for subsequent scanning. Figure 11 shows an example of coding a $9.99 price.

Syncfusion Barcode 39

Figure 11: Syncfusion Barcode 39

 

The barcode in Figure 11 was created using the following CSCS code:

AddSfCode39Barcode(locSFWidget, "Code39""$9.99"600400);

Note that we can reuse the same location for locSFWidget that we used before, placing into it a different widget and hiding the widget that was there before. The C# code is very similar to the Code Listing 26, so we will skip it.

Picker

We already saw the Syncfusion Picker in action in Chapter 3. The cool part about this control is that it’s very easy to configure it to have multiple columns. However, here we are going to look at a harder part to implement—a picker with an image and a text together. See how it looks on iOS and Android in Figure 12.

Syncfusion Picker Control on iOS and on Android

Figure 12: Syncfusion Picker Control on iOS and on Android

The CSCS code to produce the picker in Figure 12 is the following:

AddSfPicker(locSFWidget, "cbCurrency""75"200380);
currencies = {"EUR",   "USD",   "GBP",   "CHF",   "BTC""JPY",  "CNY",

              "MXN",   "RUB",   "BRL",   "SAR"};
flags      = {"eu_EU""en_US""en_GB""de_CH""BTC""ja_JP""zh_CN",

              "es_MX""ru_RU""pt_BR""ar_SA"};
AddWidgetData(cbCurrency, currencies);
AddWidgetImages(cbCurrency, flags);
SetSize(cbCurrency, 8040);
SetText(cbCurrency, "BTC");

We are going to see how to implement it on Android because it requires more effort—we have to manually create a view for each picker entry.

We also have to manually create different views for selected and unselected entries. On top of that, we have to reload all views on each selection. See Code Listing 27 for details.

Code Listing 27: A Fragment of the CreatePicker Method for Android

void CreatePicker()
{
  m_picker = new SfPicker(m_context);

  string str1 = "", str2 = "", str3 = "", str4 = "";
  Utils.Extract(m_data, ref str1, ref str2, ref str3, ref str4);
  if (!string.IsNullOrEmpty(str1)) {
    double rowHeight = Utils.ConvertToDouble(str1);
    if (rowHeight > 0) {
      rowHeight = AutoScaleFunction.TransformSize((int)rowHeight,
                                    UtilsDroid.GetScreenSize().Width);
      m_picker.ItemHeight = rowHeight;
    }
  }
  m_picker.ShowHeader = !string.IsNullOrEmpty(str2);
  if (m_picker.ShowHeader) {
    m_picker.HeaderHeight = 60;
    m_picker.HeaderText = str2;
    m_picker.HeaderBackgroundColor = Color.Transparent;
    m_picker.HeaderTextColor = Color.Black;
  }
  m_picker.ShowColumnHeader = !string.IsNullOrEmpty(str3);
  if (m_picker.ShowColumnHeader) {
    m_picker.ColumnHeaderHeight = 60;
    m_picker.ColumnHeaderText = str3;
    m_picker.ColumnHeaderBackgroundColor = Color.Transparent;
    m_picker.ColumnHeaderTextColor = Color.Black;
  }

  m_picker.ShowFooter    = false;
  m_picker.SelectedIndex = 0;
  m_picker.PickerMode    = PickerMode.Default;
  m_picker.BorderColor   = Color.Black;
  m_picker.PickerWidth   = m_width;
  m_picker.PickerHeight  = m_height;

  m_picker.OnSelectionChanged += (sender, e) => {
    ActionDelegate?.Invoke(WidgetName, e.NewValue.ToString());
  };

  var linePic = UtilsDroid.String2Pic("grayline");
  m_picker.OnPickerItemLoaded += (sender, e) => {
    if (m_pics == null) {
      return;
    }
    m_picker.HeaderBackgroundColor = Color.Transparent;
    m_picker.HeaderTextColor = Color.Black;
    m_picker.UnSelectedItemTextColor = Color.LightGray;
    m_picker.SelectedItemTextcolor = Color.Black;

    int row = e.Row;
    bool isSelected = row == (int)m_picker.SelectedIndex;
    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
        ViewGroup.LayoutParams.WrapContent,
        ViewGroup.LayoutParams.WrapContent
    );
    layoutParams.Height  = (int)m_picker.ItemHeight;
    layoutParams.Width   = (int)m_picker.Width;
    LinearLayout rowView = new LinearLayout(m_context) {

                           Orientation = Orientation.Vertical };

    LinearLayout rowData = new LinearLayout(m_context);
    rowData.Orientation = Orientation.Horizontal;

    if (m_pics.Count > row) {
      ImageView rowImage = new ImageView(m_context);
      rowImage.SetImageResource(m_pics[row]);
      if (!isSelected) {
        rowImage.SetColorFilter(Color.Argb(200128128128));
      } else {
        rowImage.SetColorFilter(null);
      }
      rowData.AddView(rowImage, ViewGroup.LayoutParams.WrapContent,

                                ViewGroup.LayoutParams.WrapContent);
    }
    if (m_strings != null && m_strings.Count > row) {
      TextView rowText = new TextView(m_context);
      rowText.Text = " " + m_strings[row];
      rowText.TextAlignment = m_alignment.Item2;
      rowText.SetBackgroundColor(m_bgColor);
      rowText.SetTextColor(isSelected ? m_fontColor : Color.Gray);
      rowText.Gravity = GravityFlags.CenterVertical;
      rowData.AddView(rowText, ViewGroup.LayoutParams.WrapContent,

                               ViewGroup.LayoutParams.WrapContent);
    }

    ImageView line = new ImageView(m_context);
    line.SetImageResource(linePic);
    line.LayoutParameters = new ViewGroup.LayoutParams(

                                ViewGroup.LayoutParams.MatchParent,

                                ViewGroup.LayoutParams.WrapContent);
    rowView.AddView(rowData, ViewGroup.LayoutParams.MatchParent,

                             ViewGroup.LayoutParams.WrapContent);
    rowView.AddView(line,    ViewGroup.LayoutParams.MatchParent,

                             ViewGroup.LayoutParams.WrapContent);
    rowView.LayoutParameters = layoutParams;

    e.CustomView = rowView;
  };

  ViewX = m_picker;
}

Digital Gauge

The Digital Gauge control looks especially cool when showing the current time; see Figure 13.

Syncfusion Digital Gauge

Figure 13: Syncfusion Digital Gauge

The CSCS code producing what you see in Figure 13 is the following:

AddSfDigitalGauge(locSFWidget,  "DigitalGauge"""500200);
SetValue(DigitalGauge, "value", Now("HH:mm:ss"));
SetFontColor(DigitalGauge,  "green");

Schedule(1000"timer_timeout""""timerId"1);
function timer_timeout(sender, arg)
{
  SetValue(DigitalGauge, "value", Now("HH:mm:ss"));
}

Note that the time shown in the Digital Gauge control is being updated every second. The C# wrapper over the Syncfusion Digital Gauge is shown in Code Listing 28.

Code Listing 28: The Implementation of the CreateDigitalGauge Method

void CreateDigitalGauge()
{
  m_digitalGauge = new SFDigitalGauge();
  m_digitalGauge.Frame = m_rect;

  m_digitalGauge.CharacterHeight = 36;
  m_digitalGauge.CharacterWidth = 17;
  m_digitalGauge.VerticalPadding = 10;
  m_digitalGauge.SegmentWidth = 3;

  m_digitalGauge.CharacterType = SFDigitalGaugeCharacterType.

           SFDigitalGaugeCharacterTypeEightCrossEightDotMatrix;
  m_digitalGauge.StrokeType = SFDigitalGaugeStrokeType.

           SFDigitalGaugeStrokeTypeTriangleEdge;
  m_digitalGauge.Value = (NSString)NSDate.Now.ToString();
  m_digitalGauge.DimmedSegmentAlpha = 0.11f;
  m_digitalGauge.BackgroundColor = UIColor.White;
  m_digitalGauge.CharacterColor = UIColor.Blue;
  m_digitalGauge.DimmedSegmentColor = UIColor.LightGray;

  ViewX = m_digitalGauge;
}

Circular Gauge

The Circular Gauge control is probably one of the most complex, regarding the configuration. There are many different options for it. An example with two scales is shown in Figure 14.

Syncfusion Circular Gauge on iOS and on Android

Figure 14: Syncfusion Circular Gauge on iOS and on Android

The example in Figure 14 was created using the CSCS code in Code Listing 29:

Code Listing 29: The CSCS Code to Create a Syncfusion Circular Gauge

AddSfCircularGauge(locSFWidget, "CircularGauge"""400400);
SetValue(CircularGauge, "from",               0);
SetValue(CircularGauge, "to",                 160);
SetValue(CircularGauge, "step",               10);
SetValue(CircularGauge, "value",              90);
SetValue(CircularGauge, "start_angle",        30);
SetValue(CircularGauge, "sweep_angle",        330);
SetValue(CircularGauge, "start_range2",       120);
SetValue(CircularGauge, "radius_knob",        12);
SetValue(CircularGauge, "color_needle",       "blue");
SetValue(CircularGauge, "color_knob",         "rose");
SetValue(CircularGauge, "color_labels",       "black");
SetValue(CircularGauge, "color_range1",       "green");
SetValue(CircularGauge, "color_range2",       "red");
SetValue(CircularGauge, "color_minorticks",   "gray");
SetValue(CircularGauge, "color_majorticks",   "black");
SetValue(CircularGauge, "scale2_from",        0);
SetValue(CircularGauge, "scale2_to",          100);
SetValue(CircularGauge, "scale2_interval",    5);
SetValue(CircularGauge, "scale2_rimcolor",    "yellow");
SetValue(CircularGauge, "scale2_labelcolor",  "black");

SetText(CircularGauge,  "km, mi/h");

Calendar

The Syncfusion Calendar is a nice widget displaying either a month or a year (depending on the configuration). You can get the previous or next years or months by swiping it left and right. You can also easily add appointments to the calendar. Check out Figure 15 for an example.

Syncfusion Calendar on iOS and on Android

Figure 15: Syncfusion Calendar on iOS and on Android

Here is the CSCS code that created the controls in Figure 15:

AddSfCalendar(locSFWidget, "Calendar"""450450);
AddSfAppointment(Calendar"Private Appointment",

                 "2018/01/08 13:00""2018/01/08 14:00""brown");
AddSfAppointment(Calendar"Job Interview",

                "2018/01/25 15:00""2018/01/25 16:00""green");

Image Editor

This is probably one of the coolest Syncfusion widgets. You can actually use it to edit images! See Figure 16 for an example.

Syncfusion Image Editor on iOS and on Android

Figure 16: Syncfusion Image Editor on iOS and on Android

The Syncfusion Image Editor can be created from the following CSCS code:

AddSfImageEditor(locSFWidget, "ImageEditor""library",

                 DisplayWidth, DisplayHeight);

Yes, just a one-liner! Note that DisplayWidth and DisplayHeight are special CSCS variables, indicating that the widget should take over the whole screen.

The library initialization parameter indicates that the picture will be selected by the user from a device library file. Another option is camera, meaning that the image will be taken from a device camera.

Busy Indicator

The Busy Indicator control currently contains 15 different animations that can be shown to the user while the app is doing some other work. Figure 17 contains all these 15 animations. It is a static picture, but in reality, all the images are animated.

Syncfusion BusyIndicator on iOS and Android

Figure 17: Syncfusion BusyIndicator on iOS and Android

The indicators in Figure 17 were set up in CSCS by providing different parameters during the initialization. Check out the CSCS code in Code Listing 30.

Code Listing 30: The CSCS Code to Create Syncfusion BusyIndicators

SetBackgroundColor("snow");

h = 200;
w = 200;
delta = 3;
locSFWidget1 = GetLocation("ROOT""LEFT""ROOT""TOP", delta, 12);
AddSfBusyIndicator(locSFWidget1, "BusyIndicator1""ball", h, w);

locSFWidget2 = GetLocation(BusyIndicator1, "RIGHT",

                           BusyIndicator1, "CENTER", delta);
AddSfBusyIndicator(locSFWidget2, "BusyIndicator2""battery", h, w);

locSFWidget3 = GetLocation(BusyIndicator2, "RIGHT",

                           BusyIndicator2, "CENTER", delta);
AddSfBusyIndicator(locSFWidget3, "BusyIndicator3""box", h, w);

locSFWidget4 = GetLocation(BusyIndicator1, "CENTER",

                           BusyIndicator1, "BOTTOM",  0, delta);
AddSfBusyIndicator(locSFWidget4, "BusyIndicator4""doublecircle", h, w);

locSFWidget5 = GetLocation(BusyIndicator2, "CENTER",

                           BusyIndicator2, "BOTTOM", delta, delta);
AddSfBusyIndicator(locSFWidget5, "BusyIndicator5""ecg", h, w);

locSFWidget6 = GetLocation(BusyIndicator3, "CENTER",

                           BusyIndicator3, "BOTTOM", delta, delta);
AddSfBusyIndicator(locSFWidget6, "BusyIndicator6""gear", h, w);

locSFWidget7 = GetLocation(BusyIndicator4, "CENTER",

                           BusyIndicator4, "BOTTOM",  0, delta);
AddSfBusyIndicator(locSFWidget7, "BusyIndicator7""globe", h, w);

locSFWidget8 = GetLocation(BusyIndicator5, "CENTER",

                           BusyIndicator5, "BOTTOM", delta, delta);
AddSfBusyIndicator(locSFWidget8, "BusyIndicator8""pulsing", h, w);

locSFWidget9 = GetLocation(BusyIndicator6, "CENTER",

                           BusyIndicator6, "BOTTOM", delta, delta);
AddSfBusyIndicator(locSFWidget9, "BusyIndicator9""movie", h, w);

locSFWidget10 = GetLocation(BusyIndicator7, "CENTER",

                            BusyIndicator7, "BOTTOM",  0, delta);
AddSfBusyIndicator(locSFWidget10, "BusyIndicator10""print", h, w);

locSFWidget11 = GetLocation(BusyIndicator8, "CENTER",

                            BusyIndicator8, "BOTTOM", delta, delta);
AddSfBusyIndicator(locSFWidget11, "BusyIndicator11""rectangle", h, w);

locSFWidget12 = GetLocation(BusyIndicator9, "CENTER",

                            BusyIndicator9, "BOTTOM", delta, delta);
AddSfBusyIndicator(locSFWidget12, "BusyIndicator12""rollingball", h, w);

locSFWidget13 = GetLocation(BusyIndicator10, "CENTER",

                            BusyIndicator10, "BOTTOM",  0, delta);
AddSfBusyIndicator(locSFWidget13, "BusyIndicator13""singlecircle", h, w);

locSFWidget14 = GetLocation(BusyIndicator11, "CENTER",

                            BusyIndicator11, "BOTTOM", delta, delta);
AddSfBusyIndicator(locSFWidget14, "BusyIndicator14""slicedcircle", h, w);

locSFWidget15 = GetLocation(BusyIndicator12, "CENTER",

                            BusyIndicator12, "BOTTOM", delta, delta);
AddSfBusyIndicator(locSFWidget15, "BusyIndicator15""zooming", h, w);

SetValue(BusyIndicator1,  "color""green");
SetValue(BusyIndicator2,  "color""sky_blue");
SetValue(BusyIndicator3,  "color""brown");
SetValue(BusyIndicator4,  "color""black");
SetValue(BusyIndicator5,  "color""pink");
SetValue(BusyIndicator6,  "color""dark_gray");
SetValue(BusyIndicator7,  "color""light_blue");
SetValue(BusyIndicator8,  "color""deep_sky_blue");
SetValue(BusyIndicator9,  "color""blue");
SetValue(BusyIndicator10, "color""red");
SetValue(BusyIndicator11, "color""silver");
SetValue(BusyIndicator12, "color""blue");
SetValue(BusyIndicator13, "color""blue");
SetValue(BusyIndicator14, "color""yellow");
SetValue(BusyIndicator15, "color""gray");
SetValue(BusyIndicator9,  "secondary_color""red");
SetValue(BusyIndicator12, "secondary_color""red");

Data Grid

The Data Grid control shows a list of data entries; see Figure 18. This list has different configuration options. When the user clicks on the Edit button, an extra window is shown, where the user can edit the row’s entries.

Syncfusion DataGrid After Swiping a Row to the Right and to the Left on iOS

Figure 18: Syncfusion DataGrid After Swiping a Row to the Right and to the Left on iOS

The CSCS code that created the Data Grid in Figure 18 is shown in Code Listing 31.

Code Listing 31: The CSCS Code to Create Syncfusion Data Grid

AddSfDataGrid(locSFWidget,      "DataGrid"""600625);

listCols   = {"Name""string""Age""number",

              "Profession""string""Salary""currency"};
person1    = {"Christiano""30""Soccer Player",     "60000000"};
person2    = {"Roger",      "27""Tennis Player",     "40000000"};
person3    = {"Sharon",     "47""Actress",           "30000000"};
person4    = {"Justin",     "34""Singer",            "20000000"};
person5    = {"Sergio",     "52""CEO TheBank",       "5000000"};
person6    = {"Viktor",     "41""VP Engineering",    "350000"};
person7    = {"Beat",       "44""Psychiatrist",      "280000"};
person8    = {"Larissa",    "39""Doctor",            "200000"};
person9    = {"Elena",      "29""Software Engineer""120000"};
person10   = {"Pedro",      "41""Quality Engineer",  "115000"};
person11   = {"John",       "48""Nuclear Physicist""95000"};
person12   = {"Diana",      "21""Office Manager",    "90000"};
person13   = {"Freddy",     "51""Unemployed",        "20000"};
AddWidgetData(DataGrid, listCols, "columns");
AddWidgetData(DataGrid, person1,  "item");
AddWidgetData(DataGrid, person2,  "item");
AddWidgetData(DataGrid, person3,  "item");
AddWidgetData(DataGrid, person4,  "item");
AddWidgetData(DataGrid, person5,  "item");
AddWidgetData(DataGrid, person6,  "item");
AddWidgetData(DataGrid, person7,  "item");
AddWidgetData(DataGrid, person8,  "item");
AddWidgetData(DataGrid, person9,  "item");
AddWidgetData(DataGrid, person10, "item");
AddWidgetData(DataGrid, person11, "item");
AddWidgetData(DataGrid, person12, "item");
AddWidgetData(DataGrid, person13, "item");

SetValue(DataGrid, "swipe_edit",   true);
SetValue(DataGrid, "swipe_delete"true);
SetValue(DataGrid, "allow_drag",   true);
SetValue(DataGrid, "allow_swap",   true);
SetValue(DataGrid, "allow_resize"true);
SetValue(DataGrid, "allow_sort",   true);

The column name configuration is taking place in:

AddWidgetData(DataGrid, listCols, "columns");

The format of the listCols list is the following:

     

{ columnName1, columnType1, columnName2, columnType2, …}

Note that we explicitly allow the user to sort by the column values, resize column widths, drag and drop rows in different places, and so on, as defined in the SetValue() functions at the end of Code Listing 31.

Spline Chart

The Spline Chart creates a continuous, piecewise polynomic function from some data points: see Figure 19. When you touch one of the black data points on the graph, you will see the exact value it represents.

Syncfusion Spline Chart on iOS and on Android

Figure 19: Syncfusion Spline Chart on iOS and on Android

The CSCS code that created the Spline charts in Figure 19 is shown in Code Listing 32.

Code Listing 32: The CSCS Code to Create Syncfusion Spline Chart

AddSfSplineGraph(locSFWidget, "SplineGraph"""600500);
chartData1 = {"Jan",-3"Feb",-2"Mar",0, "Apr",7"May",17,

  "Jun",23, "Jul",26"Aug"28"Sep",21"Oct",14"Nov",7"Dec",1};
chartData2 = {"Jan",-17"Feb",-19"Mar",-7"Apr",9"May",19,

  "Jun",25, "Jul",31"Aug",33"Sep",23"Oct",11"Nov",-2"Dec",-11};

chartData3 = {"Jan",23"Feb",22"Mar",25"Apr",29"May",32,

  "Jun",31"Jul",31"Aug",36"Sep",33"Oct",25"Nov",23"Dec",21};

AddWidgetData(SplineGraph, chartData1,  "Zurich",   "green:black");
AddWidgetData(SplineGraph, chartData2,  "Moscow",   "red:black");
AddWidgetData(SplineGraph, chartData3,  "Acapulco""yellow:black");

SetText(SplineGraph,  "World Temperatures 2015");
SetValue(SplineGraph, "primary_axis",   "Month");
SetValue(SplineGraph, "secondary_axis""Temperature");

Doughnut and Semi-Doughnut Charts

The Syncfusion Doughnut and Semi-Doughnut graphs are shown in Figure 20.

Syncfusion Doughnut and Semi-Doughnut Charts on Android

Figure 20: Syncfusion Doughnut and Semi-Doughnut Charts on Android

The CSCS code that created the charts in Figure 20 is shown in Code Listing 33. Note that the charts can have either a percentage value, or an absolute one. This is set up by an initialization parameter in the AddWidgetData() call (it can be either values or percent).

We also define there from which angle to which angle the graph is going to be shown. 0:360 means the full circle, and 180:360 means the upper half. All other values between 0 and 360 are possible as well.

Code Listing 33: The CSCS Code to Create Syncfusion Doughnut and Semi-Doughnut Charts

AddSfDoughnutGraph(locSFWidget, "DoughnutGraph"""600500);
chartDataF = {"USA", 368"UK", 132"Germany", 107"France", 62,

              "Sweden"30"Switzerland"26"Japan"26,

              "Canada"23"Russia"23"Austria"21};
AddWidgetData(DoughnutGraph, chartDataF,  "values""0:360");
SetText(DoughnutGraph,     "World Nobel Laureates 2017");


AddSfDoughnutGraph(locSFWidget, "SemiDoughnutGraph"""600500);
chartDataD = {"Italy"50900"France"45200"Spain"39300,

              "USA"23600, "Australia"13100};
AddWidgetData(SemiDoughnutGraph, chartDataD,  "percent""180:360");
SetText(SemiDoughnutGraph, "World Wine Production 2016");

Summary

In this chapter, we saw a few of the Syncfusion controls. There are also many controls that we did not have time to see here, for instance, a calculator, an image rotator, different list views, a diagram creator, and many others.

This chapter is also important because it can give you an idea of how to add other existing widget frameworks to CSCS.

In the next chapter, we are going to dig deeper into Syncfusion controls, looking into how to create known file types.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.