• entries
23
28
• views
20240

# Blargh

212 views

First off, big thanks to both shawn in #gamedev and EqualityAssignment here. shawn assisted me with certain event firing(the whole problem/solution was made obsolete by some other changes I made, but still), and EqualityAssignment pointed out an error I had with my UndoRedo collection. I've made a few quasi-major changes to the way things work, implemented a few more things, and discovered that a few more quasi-major changes might have to be made.

# rnfnCodeLite

## A Few Quasi-Major Changes

CodeView is no more...
I had originally seperated the CodeView and rnfnCodeLite controls so that there could be a base control and an 'external' control when the external editor was used(I'm calling the popout editor the external editor for now.) However, I was going to have CodeView kinda split whenever the splitview was activated, which would ultimately mean CodeView would add two of itself inside the first one, acting as a split panel container thing whatever-the-deuce-it-is-called. Then it hit me, if CodeView is going to have to be aware of multiple instances of itself, why not just do the same with rnfnCodeLite and do away with CodeView? And so I did. rnfnCodeLite is now self-aware of whether it is the original/base control or whether it is a secondary/child control, mainly by which constructor is called. public rnfnCodeLite() would be the default used by Designer as well as the programmer, thus the base control, and internal rnfnCodeLite(rnfnCodeLiteData) is the constructor to be called when the control is an 'child' control.

Let there be rnfnCodeLiteData...
So, even though CodeView was swallowed up by the rnfnCodeLite class, there still existed a need for a common shared data between the controls and other classes dependant on the data. Thus was rnfnCodeLiteData born, an original name if ever there was one:
using System;using System.Collections.Generic;using System.Drawing;using System.Windows.Forms;namespace rnfn.Controls.CodeLite{    internal sealed class rnfnCodeLiteData    {        internal Text text;        internal Library library;        internal Lexer lexer;        internal Font font;        internal Pen borderPen;        internal Pen gutterPen;        internal Pen backlightPen;        internal Pen unfocusedBacklightPen;        internal Pen linenumberPen;        internal Pen caretPen;        internal Pen optimizedCaretPen;        internal Pen selectionBackPen;        internal Pen selectionForePen;        internal Pen backgroundPen;        internal Pen textPen;        internal Timer caretTimer;        internal bool caretVisible;        internal TextFormatFlags stdFormatFlags=TextFormatFlags.NoPadding|                                                TextFormatFlags.ExpandTabs|                                                TextFormatFlags.PreserveGraphicsClipping|                                                TextFormatFlags.NoPrefix;        internal string externalEditorTitle;        internal bool overwriteMode;        internal ContextMenuStrip textContextMenu;        internal ContextMenuStrip iconContextMenu;        internal Icon iconCollapsed;        internal Icon iconCollapsable;        internal Icon iconCollapsableRegion;        internal Icon iconCollapseEnd;        internal Icon iconExternalEditor;        internal Image imagePopOut;        internal Image imageSticky;        internal bool optionVirtualSpace;        internal bool optionOptimizeCaretDrawing;        internal bool optionShowBar;        internal bool optionShowCollapse;        internal bool optionShowIcons;        internal bool optionShowNumbers;        internal bool optionAutoIndent;        internal bool optionNoTabs;        internal bool optionWordWrap;        internal bool optionAnnoyingBeep;        internal event EventHandler DeadspaceImageChanged;        internal event EventHandler TextPenChanged;        internal event EventHandler FontChanged;        internal event EventHandler BackgroundPenChanged;        internal void FireDeadspaceImageChangedEvent()        {            if(DeadspaceImageChanged!=null)                DeadspaceImageChanged(this,new EventArgs());        }        internal void FireTextPenChangedEvent()        {            if(TextPenChanged!=null)                TextPenChanged(this,new EventArgs());        }        internal void FireFontChangedEvent()        {            if(FontChanged!=null)                FontChanged(this,new EventArgs());        }        internal void FireBackgroundPenChangedEvent()        {            if(BackgroundPenChanged!=null)                BackgroundPenChanged(this,new EventArgs());        }    }}

And there it is as it currently stands. Mostly options and customization vars there, plus some event firers. Cause, apparently, you can't fire an event *outside* of the class it is inside of. o_O So, yeah, rnfnCodeLiteData is shared between all the rnfnCodeLite instances of the base rnfnCodeLite, and the base is responsible for the initialization of all the contents within the common rnfnCodeLiteData var. All other classes dependent on the data within have been altered as needed.

## A Few Things Implemented

Implemented most of the non-character keys, such as Enter, the directional keys, Tab, and whatnot. Would probably have gotten more done, but I spent an hour trying to figure out why the Tab key was getting ignored when it turned out that I wasn't moving the caret whenever I was tabbing, so the tab was essentially placed after the caret. :/

Carets...
The caret drawing stuff has been more fully implemented and fixed a few buggies that snuck in. I can't immediately recall if I implemented the code for when optionOptimizedCaretDrawing is set. What I call 'Optimized Caret Drawing' is just drawing over the caret with another color instead of calling Invalidate(), which would redraw the whole control. More on the redrawing of the whole control in a bit...

Word Wrap...
I've stared the implementation of the smart word wrapping option/feature. Currently, the DefaultLexer will wrap on whitespace only, though I may change this at some point. The 'smart' bit comes in with the lexers, though. I've added another abstract method to the Lexer class that is called if word wrap is turned on. This method is to return a string[] that contains the line of text divided up into the desire segments that will then be compounded into the maximum sized segments that won't scroll off the screen.

The only downside to this is that it removes part of the 'smart' from the equation, as the segments won't know how to indent properly/smartly. What I'll probably end up doing is sending an int length argument too, so it can use TextRenderer.MeasureText to get the proper size and indent the text accordingly. Note that the actual text of the line will not be altered, just the drawn.

I just realize, though, that none of the caret-moving code has been modified to handle moving on a word-wrapped line. As in, as it stands, if the word-wrap code were implemented sufficiently, pressing the down key would take you to the next line below, not the next portion of the same line... :/ Dangit, something else to mull over.

Mangled Code...
I'll probably have to go through the code before long since I was mangling it a bit trying to figure out why a few things were doing what they weren't supposed to and weren't doing what they *were* supposed to, etc. :/ Nothing major, but a few tweaks certainly wouldn't hurt things. Sadly, and partly due to the dial-up connection being in use by other parties, I didn't get to commit anything between my last edit and tonight, so there was only one grand SVN commit for all my changes. Yay.

## A Few Quasi-Major Changes To Make

On Invalidate()...
As it currently stands, when a change is made to the control, whether the color of the line numbers, or a period added to the second line, way above the view of the screen, or the blink of the caret, the screen is completely being redrawn(only the valid lines, mind you, but redrawn nonetheless.) I'm pretty sure I probably shouldn't be redrawing the client area each time a minor event occurs. Particularly if it changes nothing on the screen. I'm not quite sure how to go about it, though either. I haven't had any experience at redrawing only a small portion of an area and having it be kept insync with the rest of it. I'll have to ask around for advice(or, you know, you could just leave a comment...) or something.

Speaking of Invalidate(), whenever a change is made in one rnfnCodeLite control, whether the base/main one or one of the external editor ones, the changes aren't being made to the other visible controls. So this means that I'll have to setup some sort of event listening thing so that the other controls know when a change has been made where they should redraw. Of course, this brings us back to the potentially needless redrawing of not one, but *multiple* client areas. Blargh.

On Parsing...
Currently, whenever a KeyPress or KeyDown event is fired, the resulting code knows what lines are altered, so knows what lines to send to be reparsed by the lexer. However, I noticed earlier when testing the UndoRedo collection that when undo-ing and redo-ing, it isn't, at least yet, aware of what lines need to be reparsed. So this means that I'll have to come up with some way of flagging the lines to be reparsed. In the very least, I suppose, I could only redraw an area when the lines need to look different than they do. That would still leave the non-optimized blinking caret Invalidate()ing the control every so often, whenever the system is set to have it blink. If it does at all. I nearly missed including the code to handle a blink rate of none.

On Text Selection...
Yes, this is coming up once more. Kinda what threw me off last time, hopefully I'll have a better go at it, and actually get a decent version implemented, once I fix the current 'problems'. I plan on implementing both vertical and horizontal text selecting, and still have to implement the code for keyboard input when dealing with selecting/selected text.

Blargh. A lot of stuff to do and fix, and I'm still aways away. The control's .dll is about 30kb, not sure if I'll get to keep it under the desired 50kb, but oh well.

Apologies if the journal entry seems...pieced together, as it kinda was. Not sure I covered everything, but I think the entry is big enough. If I forgot anything 'important', there is always next time.

There are no comments to display.