DiffView.coffee 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. define [
  2. "ace/ace"
  3. "ace/mode/latex"
  4. "ace/range"
  5. "libs/backbone"
  6. ], (Ace, LatexMode, Range)->
  7. DiffView = Backbone.View.extend
  8. initialize: () ->
  9. @model.on "change:diff", () => @render()
  10. @render()
  11. render: ->
  12. diff = @model.get("diff")
  13. return unless diff?
  14. @createAceEditor()
  15. @aceEditor.setValue(@getPlainDiffContent())
  16. @aceEditor.clearSelection()
  17. session = @aceEditor.getSession()
  18. session.setMode(new LatexMode.Mode())
  19. session.setUseWrapMode(true)
  20. @insertMarkers()
  21. return @
  22. createAceEditor: () ->
  23. @$el.empty()
  24. $editor = $("<div/>")
  25. @$el.append($editor)
  26. @aceEditor = Ace.edit($editor[0])
  27. @aceEditor.setTheme("ace/theme/#{window.userSettings.theme}")
  28. @aceEditor.setReadOnly true
  29. @aceEditor.setShowPrintMargin(false)
  30. @aceEditor.on "mousemove", (e) =>
  31. position = @aceEditor.renderer.screenToTextCoordinates(e.clientX, e.clientY)
  32. e.position = position
  33. @updateVisibleNames(e)
  34. getPlainDiffContent: () ->
  35. content = ""
  36. for entry in @model.get("diff") or []
  37. content += entry.u or entry.i or entry.d or ""
  38. return content
  39. insertMarkers: () ->
  40. row = 0
  41. column = 0
  42. for entry, i in @model.get("diff") or []
  43. content = entry.u or entry.i or entry.d
  44. lines = content.split("\n")
  45. startRow = row
  46. startColumn = column
  47. if lines.length > 1
  48. endRow = startRow + lines.length - 1
  49. endColumn = lines[lines.length - 1].length
  50. else
  51. endRow = startRow
  52. endColumn = startColumn + lines[0].length
  53. row = endRow
  54. column = endColumn
  55. range = new Range.Range(
  56. startRow, startColumn, endRow, endColumn
  57. )
  58. @addMarker(range, "change-marker-#{i}", entry)
  59. addMarker: (range, id, entry) ->
  60. session = @aceEditor.getSession()
  61. markerBackLayer = @aceEditor.renderer.$markerBack
  62. markerFrontLayer = @aceEditor.renderer.$markerFront
  63. lineHeight = @aceEditor.renderer.lineHeight
  64. if entry.i? or entry.d?
  65. hue = entry.meta.user.hue()
  66. if entry.i?
  67. @_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-background", false, """
  68. background-color : hsl(#{hue}, 70%, 85%);
  69. """
  70. tag = "Added by #{entry.meta.user.name()}"
  71. if entry.d?
  72. @_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-background", false, """
  73. background-color : hsl(#{hue}, 70%, 95%);
  74. """
  75. @_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-foreground", true, """
  76. height: #{Math.round(lineHeight/2) - 1}px;
  77. border-bottom: 2px solid hsl(#{hue}, 70%, 40%);
  78. """
  79. tag = "Deleted by #{entry.meta.user.name()}"
  80. tag += " on #{entry.meta.end_ts}"
  81. @_addNameTag session, id, range, tag, """
  82. background-color : hsl(#{hue}, 70%, 85%);
  83. """
  84. _addMarkerWithCustomStyle: (session, markerLayer, range, klass, foreground, style) ->
  85. session.addMarker range, klass, (html, range, left, top, config) ->
  86. if range.isMultiLine()
  87. markerLayer.drawTextMarker(html, range, klass, config, style)
  88. else
  89. markerLayer.drawSingleLineMarker(html, range, "#{klass} ace_start", config, 0, style)
  90. , foreground
  91. _addNameTag: (session, id, range, content, style) ->
  92. @nameMarkers ||= []
  93. @nameMarkers.push
  94. range: range
  95. id: id
  96. startRange = new Range.Range(
  97. range.start.row, range.start.column
  98. range.start.row, session.getScreenLastRowColumn(range.start.row)
  99. )
  100. session.addMarker startRange, "change-name-marker", (html, range, left, top, config) ->
  101. html.push """
  102. <div
  103. id = '#{id}'
  104. class = 'change-name-marker'
  105. style = '
  106. height: #{config.lineHeight}px;
  107. top: #{top}px;
  108. left: #{left}px;
  109. '
  110. >
  111. <div
  112. class="name" style="
  113. display: none;
  114. bottom: #{config.lineHeight + 2}px;
  115. #{style}
  116. ">#{content}</div>
  117. </div>
  118. """
  119. , true
  120. updateVisibleNames: (e) ->
  121. for marker in @nameMarkers or []
  122. if marker.range.contains(e.position.row, e.position.column)
  123. $("##{marker.id}").find(".name").show()
  124. else
  125. $("##{marker.id}").find(".name").hide()
  126. return DiffView