DEV Community

Cover image for DEVLOG[0]: Journey into making no-code Flutter IDE
Mohamed Malkia
Mohamed Malkia

Posted on

DEVLOG[0]: Journey into making no-code Flutter IDE

Hey there, This is my first post here and will not be the last, I want to document my journey into making one of my dream projects in quite some time, and it's making some "IDE" for flutter development. It is something like FlutterFlow but with better customization in a desktop format and more of a license payment structure rather than a subscription model.

The Start

Before Flutter I always liked the idea of drag and drop to build UI, I got introduced to this concept with Visual Basic I remember watching youtube on how to make a calculator or how to make a browser and I did make them but they were very limited as I was a noob in software development, but the thing that attracted me into Visual Basic and later C# window development was that you can just drag a UI component and drop it into view and then add some logic and voila you got an application.

In 2019 I found Flutter which I just watched live when they announced version 1.0, and started learning it, it was the first time I started learning mobile development and I loved it, the language Dart was very simple, and Flutter itself was simple. But after using it for some time I wanted a tool that allowed me to just drag and drop but Flutter was new and a tool like that didn't exist.

After some time a tool called FlutterFlow was created, I was hyped when I heard about it so I tested it and then I started to see some things that I didn't enjoy that much, One that it's web-only and because my internet is not the best the site felt very slow and clunky to use, and also the payment method, they use a subscription model which I understand that the best choice for web-hosted software but it was just too expensive for me, and also it was very complex to learn and the code generation wasn't the best so I stopped using and kinda lost hope for a drag and drop tool for Flutter.

As much as I wanted to build my version of FlutterFlow I didn't have the technical skills to do so, so I just used Flutter as is until about 2 weeks ago when I started thinking about such a tool again.

Prototyping

2 weeks ago I started thinking about building a no-code tool for Flutter so I started researching what are the parts that make such software work, I found packages for different aspects of the app so I started testing them in isolation to see how easy or hard to use them and was able to build a drag and drop system and code generation and everything started to look more possible tried to see what technologies FlutterFlow are using but found nothing I'm assuming it Flutter but who knows, so in this devlog and many to come I was to document my journey in how I'm making a no-code tool for Flutter.

The structure

The core functionality of this app is that you drag an element and drop it into the editor and should be able to change widget properties.

Now the data structure I made might not be the best but for now, it's working, what I did was create an abstract class called Component and this component has a getter for the preview and a function called build, the getter is for the widget that gets drawn in the editor most of them have a DragTarget as the top widget so it can detect when components are dropped into it and can update the child, and the build function only returns the string that this component will generate.

Now to make component properties easy and flexible I created an abstract class called ComponentProperty<T> it takes a generic type so I can have access to methods and parameters of those types
now each property would created separately and extend ComponentProperty<T> class, this is an example of a property of type double that can be used for the width, height..etc of a component

class DoubleComponentProperty extends ComponentProperty<double> {
  DoubleComponentProperty(super.name, super.value);

  @override
  Widget get preview => ListTile(
        title: Text(name.capitalize()),
        subtitle: description == null ? null : Text(description ?? ""),
        trailing: SizedBox(
          width: 100,
          child: InputField(
            initialValue: value.toString().replaceAll(RegExp(r'([.]*0)(?!.*\d)'), ""),
            onChanged: (value) {
              valueSetter = double.tryParse(value) ?? 0;
              update();
            },
          ),
        ),
      );
}
Enter fullscreen mode Exit fullscreen mode

now each property has a name and value and a setter for the value this will later show the preview in the inspector when you select a component on the editor.

And for the components we create a component for each Widget in Flutter

I know it takes time to support all widgets but it's the best I can think of

and here is an example code for a container component

class ContainerComponent extends Component {
  ContainerComponent()
      : super(
          TextComponentProperty("name", "Container"),
          Icons.rectangle_rounded,
        );

  Component? child;

  DoubleComponentProperty width = DoubleComponentProperty("width", 100);
  DoubleComponentProperty height = DoubleComponentProperty("height", 100);
  ColorComponentProperty color = ColorComponentProperty(Colors.red);
  AlginmentComponentProperty alginment = AlginmentComponentProperty("alignment", AlignmentType.topLeft);
  DoubleComponentProperty radius = DoubleComponentProperty("radius", 0);

  @override
  List<ComponentProperty> get properties => [
        alginment,
        color,
        width,
        height,
        radius,
      ];

  @override
  String build() {
    if (child == null) {
      return """
Container(
  alignment: ${alginment.value.toString()},
  decoration: BoxDecoration(
    borderRadius: BorderRadius.circular(${radius.value}),
    color: Color(0x${color.value.value.toRadixString(16)}),
  ),
  width: ${width.value},
  height: ${height.value},
)
""";
    }
    return """
Container(
  alignment: ${alginment.value.toString()},
  decoration: BoxDecoration(
    borderRadius: BorderRadius.circular(${radius.value}),
    color: Color(0x${color.value.value.toRadixString(16)}),
  ),
  width: ${width.value},
  height: ${height.value},
  child: ${child?.build()},
)
""";
  }

  @override
  Component get object => ContainerComponent();

  @override
  Widget get preview => DragTarget<Component>(
        onAcceptWithDetails: (details) {
          child = details.data;
        },
        builder: (context, candidateData, rejectedData) {
          return GestureDetector(
            onTap: () => onSelect(),
            child: Container(
              alignment: alginment.value.alignment,
              height: height.value,
              width: width.value,
              decoration: BoxDecoration(
                color: color.value,
                borderRadius: BorderRadius.circular(radius.value),
              ),
              child: child?.preview,
            ),
          );
        },
      );
}
Enter fullscreen mode Exit fullscreen mode

this is the widget responsible for drawing a container on the editor and generating the code for it later.

For dragging I'm using Draggable widget that comes with Flutter
it does the job very well.

Code Generation

For this in each component there is a build function that returns the string of the component, but I also use a package made by the dart team called code_builder for generating the stateless widget that wraps everything, and dart_style to do code formatting.

Now this shows the basic structure of my data for the moment although I'm thinking about changing the component system at the moment this is how I store things. the UI of the app is still experimental it's not the best but it does the job for the moment.

Image description

Top comments (0)