github.com/jmigpin/editor@v1.6.0/util/iout/iorw/rwedit/input.go (about)

     1  package rwedit
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"unicode"
     7  
     8  	"github.com/jmigpin/editor/util/uiutil/event"
     9  )
    10  
    11  //godebug:annotatefile
    12  
    13  func HandleInput(ctx *Ctx, ev interface{}) (event.Handled, error) {
    14  	in := &Input{ctx, ev}
    15  	return in.handle()
    16  }
    17  
    18  //----------
    19  
    20  type Input struct {
    21  	ctx *Ctx
    22  	ev  interface{}
    23  }
    24  
    25  func (in *Input) handle() (event.Handled, error) {
    26  	switch ev := in.ev.(type) {
    27  	case *event.KeyDown:
    28  		return in.onKeyDown(ev)
    29  	case *event.MouseDown:
    30  		return in.onMouseDown(ev)
    31  	case *event.MouseDragMove:
    32  		return in.onMouseDragMove(ev)
    33  	case *event.MouseDragEnd:
    34  		return in.onMouseDragEnd(ev)
    35  	case *event.MouseClick:
    36  		return in.onMouseClick(ev)
    37  	case *event.MouseDoubleClick:
    38  		return in.onMouseDoubleClick(ev)
    39  	case *event.MouseTripleClick:
    40  		return in.onMouseTripleClick(ev)
    41  	}
    42  	return false, nil
    43  }
    44  
    45  //----------
    46  
    47  func (in *Input) onMouseDown(ev *event.MouseDown) (event.Handled, error) {
    48  	switch ev.Button {
    49  	case event.ButtonLeft:
    50  		if ev.Mods.ClearLocks().Is(event.ModShift) {
    51  			MoveCursorToPoint(in.ctx, ev.Point, true)
    52  		} else {
    53  			MoveCursorToPoint(in.ctx, ev.Point, false)
    54  		}
    55  		return true, nil
    56  	case event.ButtonWheelUp:
    57  		ScrollUp(in.ctx, true)
    58  	case event.ButtonWheelDown:
    59  		ScrollUp(in.ctx, false)
    60  	}
    61  	return false, nil
    62  }
    63  
    64  //----------
    65  
    66  func (in *Input) onMouseDragMove(ev *event.MouseDragMove) (event.Handled, error) {
    67  	if ev.Buttons.Has(event.ButtonLeft) {
    68  		MoveCursorToPoint(in.ctx, ev.Point, true)
    69  		return true, nil
    70  	}
    71  	return false, nil
    72  }
    73  func (in *Input) onMouseDragEnd(ev *event.MouseDragEnd) (event.Handled, error) {
    74  	switch ev.Button {
    75  	case event.ButtonLeft:
    76  		MoveCursorToPoint(in.ctx, ev.Point, true)
    77  		return true, nil
    78  	}
    79  	return false, nil
    80  }
    81  
    82  //----------
    83  
    84  func (in *Input) onMouseClick(ev *event.MouseClick) (event.Handled, error) {
    85  	switch ev.Button {
    86  	case event.ButtonMiddle:
    87  		MoveCursorToPoint(in.ctx, ev.Point, false)
    88  		Paste(in.ctx, event.CIPrimary)
    89  		return true, nil
    90  	}
    91  	return false, nil
    92  }
    93  
    94  func (in *Input) onMouseDoubleClick(ev *event.MouseDoubleClick) (event.Handled, error) {
    95  	switch ev.Button {
    96  	case event.ButtonLeft:
    97  		MoveCursorToPoint(in.ctx, ev.Point, false)
    98  		err := SelectWord(in.ctx)
    99  		// can select at EOF but avoid error msg
   100  		if errors.Is(err, io.EOF) {
   101  			err = nil
   102  		}
   103  
   104  		return true, err
   105  	}
   106  	return false, nil
   107  }
   108  
   109  func (in *Input) onMouseTripleClick(ev *event.MouseTripleClick) (event.Handled, error) {
   110  	switch ev.Button {
   111  	case event.ButtonLeft:
   112  		MoveCursorToPoint(in.ctx, ev.Point, false)
   113  		err := SelectLine(in.ctx)
   114  		return true, err
   115  	}
   116  	return false, nil
   117  }
   118  
   119  //----------
   120  
   121  func (in *Input) onKeyDown(ev *event.KeyDown) (_ event.Handled, err error) {
   122  	mcl := ev.Mods.ClearLocks()
   123  
   124  	makeCursorVisible := func() {
   125  		if err == nil {
   126  			in.ctx.Fns.MakeIndexVisible(in.ctx.C.Index())
   127  		}
   128  	}
   129  
   130  	switch ev.KeySym {
   131  	case event.KSymAltL,
   132  		event.KSymAltGr,
   133  		event.KSymShiftL,
   134  		event.KSymShiftR,
   135  		event.KSymControlL,
   136  		event.KSymControlR,
   137  		event.KSymCapsLock,
   138  		event.KSymNumLock,
   139  		event.KSymInsert,
   140  		event.KSymEscape,
   141  		event.KSymSuperL: // windows key
   142  		// ignore these
   143  	case event.KSymRight:
   144  		switch {
   145  		case mcl.Is(event.ModCtrl | event.ModShift):
   146  			err = MoveCursorJumpRight(in.ctx, true)
   147  		case mcl.Is(event.ModCtrl):
   148  			err = MoveCursorJumpRight(in.ctx, false)
   149  		case mcl.Is(event.ModShift):
   150  			err = MoveCursorRight(in.ctx, true)
   151  		default:
   152  			err = MoveCursorRight(in.ctx, false)
   153  		}
   154  		makeCursorVisible()
   155  		return true, err
   156  	case event.KSymLeft:
   157  		switch {
   158  		case mcl.Is(event.ModCtrl | event.ModShift):
   159  			err = MoveCursorJumpLeft(in.ctx, true)
   160  		case mcl.Is(event.ModCtrl):
   161  			err = MoveCursorJumpLeft(in.ctx, false)
   162  		case mcl.Is(event.ModShift):
   163  			err = MoveCursorLeft(in.ctx, true)
   164  		default:
   165  			err = MoveCursorLeft(in.ctx, false)
   166  		}
   167  		makeCursorVisible()
   168  		return true, err
   169  	case event.KSymUp:
   170  		switch {
   171  		case mcl.Is(event.ModCtrl | event.ModAlt):
   172  			err = MoveLineUp(in.ctx)
   173  		//case mcl.Is(event.ModCtrl | event.ModShift):
   174  		//err = MoveCursorJumpUp(in.ctx, true)
   175  		//case mcl.Is(event.ModCtrl):
   176  		//err = MoveCursorJumpUp(in.ctx, false)
   177  		case mcl.HasAny(event.ModShift):
   178  			MoveCursorUp(in.ctx, true)
   179  		default:
   180  			MoveCursorUp(in.ctx, false)
   181  		}
   182  		makeCursorVisible()
   183  		return true, err
   184  	case event.KSymDown:
   185  		switch {
   186  		case mcl.Is(event.ModCtrl | event.ModShift | event.ModAlt):
   187  			err = DuplicateLines(in.ctx)
   188  		case mcl.Is(event.ModCtrl | event.ModAlt):
   189  			err = MoveLineDown(in.ctx)
   190  		//case mcl.Is(event.ModCtrl | event.ModShift):
   191  		//err = MoveCursorJumpDown(in.ctx, true)
   192  		//case mcl.Is(event.ModCtrl):
   193  		//err = MoveCursorJumpDown(in.ctx, false)
   194  		case mcl.HasAny(event.ModShift):
   195  			MoveCursorDown(in.ctx, true)
   196  		default:
   197  			MoveCursorDown(in.ctx, false)
   198  		}
   199  		makeCursorVisible()
   200  		return true, err
   201  	case event.KSymHome:
   202  		switch {
   203  		case mcl.Is(event.ModCtrl | event.ModShift):
   204  			StartOfString(in.ctx, true)
   205  		case mcl.Is(event.ModCtrl):
   206  			StartOfString(in.ctx, false)
   207  		case mcl.Is(event.ModShift):
   208  			err = StartOfLine(in.ctx, true)
   209  		default:
   210  			err = StartOfLine(in.ctx, false)
   211  		}
   212  		makeCursorVisible()
   213  		return true, err
   214  	case event.KSymEnd:
   215  		switch {
   216  		case mcl.Is(event.ModCtrl | event.ModShift):
   217  			EndOfString(in.ctx, true)
   218  		case mcl.Is(event.ModCtrl):
   219  			EndOfString(in.ctx, false)
   220  		case mcl.Is(event.ModShift):
   221  			err = EndOfLine(in.ctx, true)
   222  		default:
   223  			err = EndOfLine(in.ctx, false)
   224  		}
   225  		makeCursorVisible()
   226  		return true, err
   227  	case event.KSymBackspace:
   228  		err = Backspace(in.ctx)
   229  		makeCursorVisible()
   230  		return true, err
   231  	case event.KSymDelete:
   232  		err = Delete(in.ctx)
   233  		makeCursorVisible() // TODO: on delete?
   234  		return true, err
   235  	case event.KSymReturn:
   236  		err = AutoIndent(in.ctx)
   237  		makeCursorVisible()
   238  		return true, err
   239  	case event.KSymTabLeft:
   240  		err = TabLeft(in.ctx)
   241  		makeCursorVisible()
   242  		return true, err
   243  	case event.KSymTab:
   244  		switch {
   245  		case mcl.Is(event.ModShift):
   246  			// TODO: using KSymTabLeft case, this still needed?
   247  			err = TabLeft(in.ctx)
   248  		default:
   249  			err = TabRight(in.ctx)
   250  		}
   251  		makeCursorVisible()
   252  		return true, err
   253  	case event.KSymSpace:
   254  		// ensure space even if modifiers are present
   255  		err = InsertString(in.ctx, " ")
   256  		makeCursorVisible()
   257  		return true, err
   258  	case event.KSymPageUp:
   259  		PageUp(in.ctx, true)
   260  		return true, nil
   261  	case event.KSymPageDown:
   262  		PageUp(in.ctx, false)
   263  		return true, nil
   264  	default:
   265  		switch {
   266  		case mcl.Is(event.ModCtrl):
   267  			switch ev.KeySym {
   268  			case event.KSymD:
   269  				err = Comment(in.ctx)
   270  				return true, err
   271  			case event.KSymC:
   272  				err = Copy(in.ctx)
   273  				return true, err
   274  			case event.KSymX:
   275  				err = Cut(in.ctx)
   276  				return true, err
   277  			case event.KSymV:
   278  				Paste(in.ctx, event.CIClipboard)
   279  				return true, nil
   280  			case event.KSymK:
   281  				err = RemoveLines(in.ctx)
   282  				return true, nil
   283  			case event.KSymA:
   284  				err = SelectAll(in.ctx)
   285  				return true, nil
   286  			case event.KSymZ:
   287  				err = Undo(in.ctx)
   288  				return true, nil
   289  			}
   290  		case mcl.Is(event.ModCtrl | event.ModShift):
   291  			switch ev.KeySym {
   292  			case event.KSymD:
   293  				err = Uncomment(in.ctx)
   294  				return true, err
   295  			case event.KSymZ:
   296  				err = Redo(in.ctx)
   297  				return true, nil
   298  			}
   299  		case ev.KeySym >= event.KSymF1 && ev.KeySym <= event.KSymF12:
   300  			// do nothing
   301  		case !unicode.IsPrint(ev.Rune):
   302  			// do nothing
   303  		default:
   304  			err = InsertString(in.ctx, string(ev.Rune))
   305  			makeCursorVisible()
   306  			return true, err
   307  		}
   308  	}
   309  	return false, nil
   310  }