mplekunov / CalculatorApp

GNU General Public License v3.0
1 stars 0 forks source link

Editing Feature #14

Closed mplekunov closed 2 years ago

mplekunov commented 2 years ago

It works and all... but implementation for that feature should not be provided in calculatorFragment class... It's too messy code wise and should be cleaned up.

Possibly I could create another class, do all magic there and then use its interface methods depending on situation? Since this feature is heavily dependent on the "binding" variable as it needs an access to the buttons and stuff... I think I could give that class either a binding object or an instance of calculatorFragment class...

On the second thought providing it with binding object is better. The only issue here is that I will need to move my button to enums mappings to somewhere else??? I think I need to create 2 classes, or 1 class and one object class. Object class will be responsible for binding mappings... Then I could use aggregation... and through aggregation I could pass that object to all class that would require that binding... Have to take into consideration the fact that buttons will be "null" until "onViewCreated" is called in the calculatorFragment though.

mplekunov commented 2 years ago

Let's start with this

mplekunov commented 2 years ago

So.... After... a while... The only solution I see right now is to create a clickable abstract class which will be extended by "Number", "Function", "Operator" sub classes that will provide completed implementation to spannable object in question...

The way I see it right now is something like that: I have a viewModel which accepts Input in the form of different "Tokens" (Enums) like Numbers, Functions or Operators. This viewModel returns corrected input and output (both formatted and transformed as needed)

My Editing Mode is nothing more than just "additional" feature to your common calculator... As such, it should be kind of like a module which can be "attached" to the current program.

As a "feature module" it accepts existing input (from viewModel ?!) and converts it to the "spannable" or "editable" input depending on the type of the token it is dealing with. E.g. Logic for Numbers is different compared to the logic for Operators or Functions, hence is the reason for multiple classes each of which will implement my clickable abstract class.

TLDR;

Clickable gets viewMode Clickable gets Index (index of a token that needs to be transformed to Clickable) Clickable gets Style (contains colors and other style stuff which is used for styling in Clickable) Clickable gets ButtonMap (keys are buttonTypes and values are set of buttons that corresponds to each key) Clickable gets SpannableStringBuilder (it has to modify it depending on situation)

and uses all of that to implement a ClickableSpan() for particular token at specified index

I don't like that I have to provide ButtonMap, Spannable and index as constructor values... There should be a better implementation but I can't see it right now.

mplekunov commented 2 years ago

Well... I rewrote it a bit differently... All in all it's a temporary solution... There are still things to work on to make it as best as possible. However, it's miles better than what it was originally.

mplekunov commented 2 years ago

There are still 2 main issues

  1. Styling
  2. InputFormat

Styling can be potentially fixed by creation of new class which will store style info for input output an calculator buttons (or there could be several classes for each element... like Input/Output will be related to TextStyle and Operation/Function/Number/Functional buttons will be related to ButtonStyle)

InputFormat is a bit harder... I can do it dirty and put white-spaces between tokens (digits/operators/functions) to make expression more readable... however, in that case, if I will ever want to replace the format... I would need to do it twice in two different files...

Have to come up with something better than that

mplekunov commented 2 years ago

didn't know it will close on merge

mplekunov commented 2 years ago

While sleeping I came up with a possible solution... So, the only reason why I'm passing binding object is to initialize textviews (input and output) after specific operations... All in all this approach sucks and I know it...

Possible solution would be to use livedata and return livedata from my SpannableInput class (which configures spannable input feature)

this livedata object will be updated accordingly when some "specific" operations are being made and if I configure lifecycle in my calculatorfragment I can catch those updates and bind them to the textview...

So far it looks like I will need 2 LiveData objects, one for input, the other for output